xref: /aosp_15_r20/external/libvpx/build/make/gen_msvs_vcxproj.sh (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1#!/bin/bash
2##
3##  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
4##
5##  Use of this source code is governed by a BSD-style license
6##  that can be found in the LICENSE file in the root of the source
7##  tree. An additional intellectual property rights grant can be found
8##  in the file PATENTS.  All contributing project authors may
9##  be found in the AUTHORS file in the root of the source tree.
10##
11
12self=$0
13self_basename=${self##*/}
14self_dirname=$(dirname "$0")
15
16. "$self_dirname/msvs_common.sh"|| exit 127
17
18show_help() {
19    cat <<EOF
20Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
21
22This script generates a Visual Studio project file from a list of source
23code files.
24
25Options:
26    --help                      Print this message
27    --exe                       Generate a project for building an Application
28    --lib                       Generate a project for creating a static library
29    --dll                       Generate a project for creating a dll
30    --static-crt                Use the static C runtime (/MT)
31    --enable-werror             Treat warnings as errors (/WX)
32    --target=isa-os-cc          Target specifier (required)
33    --out=filename              Write output to a file [stdout]
34    --name=project_name         Name of the project (required)
35    --proj-guid=GUID            GUID to use for the project
36    --module-def=filename       File containing export definitions (for DLLs)
37    --ver=version               Version (14-16) of visual studio to generate for
38    --src-path-bare=dir         Path to root of source tree
39    -Ipath/to/include           Additional include directories
40    -DFLAG[=value]              Preprocessor macros to define
41    -Lpath/to/lib               Additional library search paths
42    -llibname                   Library to link against
43EOF
44    exit 1
45}
46
47tag_content() {
48    local tag=$1
49    local content=$2
50    shift
51    shift
52    if [ $# -ne 0 ]; then
53        echo "${indent}<${tag}"
54        indent_push
55        tag_attributes "$@"
56        echo "${indent}>${content}</${tag}>"
57        indent_pop
58    else
59        echo "${indent}<${tag}>${content}</${tag}>"
60    fi
61}
62
63generate_filter() {
64    local name=$1
65    local pats=$2
66    local file_list_sz
67    local i
68    local f
69    local saveIFS="$IFS"
70    local pack
71    echo "generating filter '$name' from ${#file_list[@]} files" >&2
72    IFS=*
73
74    file_list_sz=${#file_list[@]}
75    for i in ${!file_list[@]}; do
76        f=${file_list[i]}
77        for pat in ${pats//;/$IFS}; do
78            if [ "${f##*.}" == "$pat" ]; then
79                unset file_list[i]
80
81                objf=$(echo ${f%.*}.obj \
82                       | sed -e "s,$src_path_bare,," \
83                             -e 's/^[\./]\+//g' -e 's,[:/ ],_,g')
84
85                if ([ "$pat" == "asm" ] || [ "$pat" == "s" ] || [ "$pat" == "S" ]) && $uses_asm; then
86                    # Avoid object file name collisions, i.e. vpx_config.c and
87                    # vpx_config.asm produce the same object file without
88                    # this additional suffix.
89                    objf=${objf%.obj}_asm.obj
90                    open_tag CustomBuild \
91                        Include="$f"
92                    for plat in "${platforms[@]}"; do
93                        for cfg in Debug Release; do
94                            tag_content Message "Assembling %(Filename)%(Extension)" \
95                                Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
96                            tag_content Command "$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)$objf" \
97                                Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
98                            tag_content Outputs "\$(IntDir)$objf" \
99                                Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
100                        done
101                    done
102                    close_tag CustomBuild
103                elif [ "$pat" == "c" ] || \
104                     [ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then
105                    open_tag ClCompile \
106                        Include="$f"
107                    # Separate file names with Condition?
108                    tag_content ObjectFileName "\$(IntDir)$objf"
109                    # Check for AVX and turn it on to avoid warnings.
110                    if [[ $f =~ avx.?\.c$ ]]; then
111                        tag_content AdditionalOptions "/arch:AVX"
112                    fi
113                    close_tag ClCompile
114                elif [ "$pat" == "h" ] ; then
115                    tag ClInclude \
116                        Include="$f"
117                elif [ "$pat" == "vcxproj" ] ; then
118                    open_tag ProjectReference \
119                        Include="$f"
120                    depguid=`grep ProjectGuid "$f" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
121                    tag_content Project "$depguid"
122                    tag_content ReferenceOutputAssembly false
123                    close_tag ProjectReference
124                else
125                    tag None \
126                        Include="$f"
127                fi
128
129                break
130            fi
131        done
132    done
133
134    IFS="$saveIFS"
135}
136
137# Process command line
138unset target
139for opt in "$@"; do
140    optval="${opt#*=}"
141    case "$opt" in
142        --help|-h) show_help
143        ;;
144        --target=*)
145            target="${optval}"
146            platform_toolset=$(echo ${target} | awk 'BEGIN{FS="-"}{print $4}')
147            case "$platform_toolset" in
148                clangcl) platform_toolset="ClangCl"
149                ;;
150                "")
151                ;;
152                *) die Unrecognized Visual Studio Platform Toolset in $opt
153                ;;
154            esac
155        ;;
156        --out=*) outfile="$optval"
157        ;;
158        --name=*) name="${optval}"
159        ;;
160        --proj-guid=*) guid="${optval}"
161        ;;
162        --module-def=*) module_def="${optval}"
163        ;;
164        --exe) proj_kind="exe"
165        ;;
166        --dll) proj_kind="dll"
167        ;;
168        --lib) proj_kind="lib"
169        ;;
170        --as=*) as="${optval}"
171        ;;
172        --src-path-bare=*)
173            src_path_bare=$(fix_path "$optval")
174            src_path_bare=${src_path_bare%/}
175        ;;
176        --static-crt) use_static_runtime=true
177        ;;
178        --enable-werror) werror=true
179        ;;
180        --ver=*)
181            vs_ver="$optval"
182            case "$optval" in
183                1[4-7])
184                ;;
185                *) die Unrecognized Visual Studio Version in $opt
186                ;;
187            esac
188        ;;
189        -I*)
190            opt=${opt##-I}
191            opt=$(fix_path "$opt")
192            opt="${opt%/}"
193            incs="${incs}${incs:+;}&quot;${opt}&quot;"
194            yasmincs="${yasmincs} -I&quot;${opt}&quot;"
195        ;;
196        -D*) defines="${defines}${defines:+;}${opt##-D}"
197        ;;
198        -L*) # fudge . to $(OutDir)
199            if [ "${opt##-L}" == "." ]; then
200                libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
201            else
202                 # Also try directories for this platform/configuration
203                 opt=${opt##-L}
204                 opt=$(fix_path "$opt")
205                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}&quot;"
206                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)/\$(Configuration)&quot;"
207                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)&quot;"
208            fi
209        ;;
210        -l*) libs="${libs}${libs:+ }${opt##-l}.lib"
211        ;;
212        -*) die_unknown $opt
213        ;;
214        *)
215            # The paths in file_list are fixed outside of the loop.
216            file_list[${#file_list[@]}]="$opt"
217            case "$opt" in
218                 *.asm|*.[Ss]) uses_asm=true
219                 ;;
220            esac
221        ;;
222    esac
223done
224
225# Make one call to fix_path for file_list to improve performance.
226fix_file_list file_list
227
228outfile=${outfile:-/dev/stdout}
229guid=${guid:-`generate_uuid`}
230uses_asm=${uses_asm:-false}
231
232[ -n "$name" ] || die "Project name (--name) must be specified!"
233[ -n "$target" ] || die "Target (--target) must be specified!"
234
235if ${use_static_runtime:-false}; then
236    release_runtime=MultiThreaded
237    debug_runtime=MultiThreadedDebug
238    lib_sfx=mt
239else
240    release_runtime=MultiThreadedDLL
241    debug_runtime=MultiThreadedDebugDLL
242    lib_sfx=md
243fi
244
245# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
246# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
247# debug exe, so this may need to be refactored later.
248for lib in ${libs}; do
249    if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
250        lib=${lib%.lib}d.lib
251    fi
252    debug_libs="${debug_libs}${debug_libs:+ }${lib}"
253done
254debug_libs=${debug_libs// /;}
255libs=${libs// /;}
256
257
258# List of all platforms supported for this target
259case "$target" in
260    x86_64*)
261        platforms[0]="x64"
262        asm_Debug_cmdline="${as} -Xvc -gcv8 -f win64 ${yasmincs} &quot;%(FullPath)&quot;"
263        asm_Release_cmdline="${as} -Xvc -f win64 ${yasmincs} &quot;%(FullPath)&quot;"
264    ;;
265    x86*)
266        platforms[0]="Win32"
267        asm_Debug_cmdline="${as} -Xvc -gcv8 -f win32 ${yasmincs} &quot;%(FullPath)&quot;"
268        asm_Release_cmdline="${as} -Xvc -f win32 ${yasmincs} &quot;%(FullPath)&quot;"
269    ;;
270    arm64*)
271        platforms[0]="ARM64"
272        # As of Visual Studio 2022 17.5.5, clang-cl does not support ARM64EC.
273        if [ "$vs_ver" -ge 17 -a "$platform_toolset" != "ClangCl" ]; then
274            platforms[1]="ARM64EC"
275        fi
276        asm_Debug_cmdline="armasm64 -nologo -oldit &quot;%(FullPath)&quot;"
277        asm_Release_cmdline="armasm64 -nologo -oldit &quot;%(FullPath)&quot;"
278    ;;
279    arm*)
280        platforms[0]="ARM"
281        asm_Debug_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
282        asm_Release_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
283    ;;
284    *) die "Unsupported target $target!"
285    ;;
286esac
287
288generate_vcxproj() {
289    echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
290    open_tag Project \
291        DefaultTargets="Build" \
292        ToolsVersion="4.0" \
293        xmlns="http://schemas.microsoft.com/developer/msbuild/2003" \
294
295    open_tag ItemGroup \
296        Label="ProjectConfigurations"
297    for plat in "${platforms[@]}"; do
298        for config in Debug Release; do
299            open_tag ProjectConfiguration \
300                Include="$config|$plat"
301            tag_content Configuration $config
302            tag_content Platform $plat
303            close_tag ProjectConfiguration
304        done
305    done
306    close_tag ItemGroup
307
308    open_tag PropertyGroup \
309        Label="Globals"
310        tag_content ProjectGuid "{${guid}}"
311        tag_content RootNamespace ${name}
312        tag_content Keyword ManagedCProj
313        if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then
314            tag_content AppContainerApplication true
315            # The application type can be one of "Windows Store",
316            # "Windows Phone" or "Windows Phone Silverlight". The
317            # actual value doesn't matter from the libvpx point of view,
318            # since a static library built for one works on the others.
319            # The PlatformToolset field needs to be set in sync with this;
320            # for Windows Store and Windows Phone Silverlight it should be
321            # v120 while it should be v120_wp81 if the type is Windows Phone.
322            tag_content ApplicationType "Windows Store"
323            tag_content ApplicationTypeRevision 8.1
324        fi
325        if [ "${platforms[0]}" = "ARM64" ]; then
326            # Require the first Visual Studio version to have ARM64 support.
327            tag_content MinimumVisualStudioVersion 15.9
328        fi
329        if [ $vs_ver -eq 15 ] && [ "${platforms[0]}" = "ARM64" ]; then
330            # Since VS 15 does not have a 'use latest SDK version' facility,
331            # specifically require the contemporaneous SDK with official ARM64
332            # support.
333            tag_content WindowsTargetPlatformVersion 10.0.17763.0
334        fi
335    close_tag PropertyGroup
336
337    tag Import \
338        Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
339
340    for plat in "${platforms[@]}"; do
341        for config in Release Debug; do
342            open_tag PropertyGroup \
343                Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \
344                Label="Configuration"
345            if [ "$proj_kind" = "exe" ]; then
346                tag_content ConfigurationType Application
347            elif [ "$proj_kind" = "dll" ]; then
348                tag_content ConfigurationType DynamicLibrary
349            else
350                tag_content ConfigurationType StaticLibrary
351            fi
352            if [ -n "$platform_toolset" ]; then
353                tag_content PlatformToolset "$platform_toolset"
354            else
355                if [ "$vs_ver" = "14" ]; then
356                    tag_content PlatformToolset v140
357                fi
358                if [ "$vs_ver" = "15" ]; then
359                    tag_content PlatformToolset v141
360                fi
361                if [ "$vs_ver" = "16" ]; then
362                    tag_content PlatformToolset v142
363                fi
364                if [ "$vs_ver" = "17" ]; then
365                    tag_content PlatformToolset v143
366                fi
367            fi
368            tag_content CharacterSet Unicode
369            if [ "$config" = "Release" ]; then
370                tag_content WholeProgramOptimization true
371            fi
372            close_tag PropertyGroup
373        done
374    done
375
376    tag Import \
377        Project="\$(VCTargetsPath)\\Microsoft.Cpp.props"
378
379    open_tag ImportGroup \
380        Label="PropertySheets"
381        tag Import \
382            Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" \
383            Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" \
384            Label="LocalAppDataPlatform"
385    close_tag ImportGroup
386
387    tag PropertyGroup \
388        Label="UserMacros"
389
390    for plat in "${platforms[@]}"; do
391        plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
392        for config in Debug Release; do
393            open_tag PropertyGroup \
394                Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
395            tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\"
396            tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\"
397            if [ "$proj_kind" == "lib" ]; then
398              if [ "$config" == "Debug" ]; then
399                config_suffix=d
400              else
401                config_suffix=""
402              fi
403              tag_content TargetName "${name}${lib_sfx}${config_suffix}"
404            fi
405            close_tag PropertyGroup
406        done
407    done
408
409    for plat in "${platforms[@]}"; do
410        for config in Debug Release; do
411            open_tag ItemDefinitionGroup \
412                Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
413            if [ "$name" == "vpx" ]; then
414                hostplat=$plat
415                if [ "$hostplat" == "ARM" ]; then
416                    hostplat=Win32
417                fi
418            fi
419            open_tag ClCompile
420            if [ "$config" = "Debug" ]; then
421                opt=Disabled
422                runtime=$debug_runtime
423                curlibs=$debug_libs
424                debug=_DEBUG
425            else
426                opt=MaxSpeed
427                runtime=$release_runtime
428                curlibs=$libs
429                tag_content FavorSizeOrSpeed Speed
430                debug=NDEBUG
431            fi
432            extradefines=";$defines"
433            tag_content Optimization $opt
434            tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)"
435            tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)"
436            tag_content RuntimeLibrary $runtime
437            tag_content WarningLevel Level3
438            if ${werror:-false}; then
439                tag_content TreatWarningAsError true
440            fi
441            if [ $vs_ver -ge 11 ]; then
442                # We need to override the defaults for these settings
443                # if AppContainerApplication is set.
444                tag_content CompileAsWinRT false
445                tag_content PrecompiledHeader NotUsing
446                tag_content SDLCheck false
447            fi
448            close_tag ClCompile
449            case "$proj_kind" in
450            exe)
451                open_tag Link
452                tag_content GenerateDebugInformation true
453                # Console is the default normally, but if
454                # AppContainerApplication is set, we need to override it.
455                tag_content SubSystem Console
456                close_tag Link
457                ;;
458            dll)
459                open_tag Link
460                tag_content GenerateDebugInformation true
461                tag_content ModuleDefinitionFile $module_def
462                close_tag Link
463                ;;
464            lib)
465                ;;
466            esac
467            close_tag ItemDefinitionGroup
468        done
469
470    done
471
472    open_tag ItemGroup
473    generate_filter "Source Files"   "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s;S"
474    close_tag ItemGroup
475    open_tag ItemGroup
476    generate_filter "Header Files"   "h;hm;inl;inc;xsd"
477    close_tag ItemGroup
478    open_tag ItemGroup
479    generate_filter "Build Files"    "mk"
480    close_tag ItemGroup
481    open_tag ItemGroup
482    generate_filter "References"     "vcxproj"
483    close_tag ItemGroup
484
485    tag Import \
486        Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets"
487
488    open_tag ImportGroup \
489        Label="ExtensionTargets"
490    close_tag ImportGroup
491
492    close_tag Project
493
494    # This must be done from within the {} subshell
495    echo "Ignored files list (${#file_list[@]} items) is:" >&2
496    for f in "${file_list[@]}"; do
497        echo "    $f" >&2
498    done
499}
500
501# This regexp doesn't catch most of the strings in the vcxproj format,
502# since they're like <tag>path</tag> instead of <tag attr="path" />
503# as previously. It still seems to work ok despite this.
504generate_vcxproj |
505    sed  -e '/"/s;\([^ "]\)/;\1\\;g' |
506    sed  -e '/xmlns/s;\\;/;g' > ${outfile}
507
508exit
509