1#!/bin/bash
2##
3##  Copyright (c) 2010 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
12
13self=$0
14self_basename=${self##*/}
15self_dirname=$(dirname "$0")
16EOL=$'\n'
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    --target=isa-os-cc          Target specifier (required)
32    --out=filename              Write output to a file [stdout]
33    --name=project_name         Name of the project (required)
34    --proj-guid=GUID            GUID to use for the project
35    --module-def=filename       File containing export definitions (for DLLs)
36    --ver=version               Version (7,8,9) of visual studio to generate for
37    --src-path-bare=dir         Path to root of source tree
38    -Ipath/to/include           Additional include directories
39    -DFLAG[=value]              Preprocessor macros to define
40    -Lpath/to/lib               Additional library search paths
41    -llibname                   Library to link against
42EOF
43    exit 1
44}
45
46die() {
47    echo "${self_basename}: $@" >&2
48    exit 1
49}
50
51die_unknown(){
52    echo "Unknown option \"$1\"." >&2
53    echo "See ${self_basename} --help for available options." >&2
54    exit 1
55}
56
57generate_uuid() {
58    local hex="0123456789ABCDEF"
59    local i
60    local uuid=""
61    local j
62    #93995380-89BD-4b04-88EB-625FBE52EBFB
63    for ((i=0; i<32; i++)); do
64        (( j = $RANDOM % 16 ))
65        uuid="${uuid}${hex:$j:1}"
66    done
67    echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
68}
69
70indent1="    "
71indent=""
72indent_push() {
73    indent="${indent}${indent1}"
74}
75indent_pop() {
76    indent="${indent%${indent1}}"
77}
78
79tag_attributes() {
80    for opt in "$@"; do
81        optval="${opt#*=}"
82        [ -n "${optval}" ] ||
83            die "Missing attribute value in '$opt' while generating $tag tag"
84        echo "${indent}${opt%%=*}=\"${optval}\""
85    done
86}
87
88open_tag() {
89    local tag=$1
90    shift
91    if [ $# -ne 0 ]; then
92        echo "${indent}<${tag}"
93        indent_push
94        tag_attributes "$@"
95        echo "${indent}>"
96    else
97        echo "${indent}<${tag}>"
98        indent_push
99    fi
100}
101
102close_tag() {
103    local tag=$1
104    indent_pop
105    echo "${indent}</${tag}>"
106}
107
108tag() {
109    local tag=$1
110    shift
111    if [ $# -ne 0 ]; then
112        echo "${indent}<${tag}"
113        indent_push
114        tag_attributes "$@"
115        indent_pop
116        echo "${indent}/>"
117    else
118        echo "${indent}<${tag}/>"
119    fi
120}
121
122generate_filter() {
123    local var=$1
124    local name=$2
125    local pats=$3
126    local file_list_sz
127    local i
128    local f
129    local saveIFS="$IFS"
130    local pack
131    echo "generating filter '$name' from ${#file_list[@]} files" >&2
132    IFS=*
133
134    open_tag Filter \
135        Name=$name \
136        Filter=$pats \
137        UniqueIdentifier=`generate_uuid` \
138
139    file_list_sz=${#file_list[@]}
140    for i in ${!file_list[@]}; do
141        f=${file_list[i]}
142        for pat in ${pats//;/$IFS}; do
143            if [ "${f##*.}" == "$pat" ]; then
144                unset file_list[i]
145
146                objf=$(echo ${f%.*}.obj | sed -e 's/^[\./]\+//g' -e 's,/,_,g')
147                open_tag File RelativePath="./$f"
148
149                if [ "$pat" == "asm" ] && $asm_use_custom_step; then
150                    for plat in "${platforms[@]}"; do
151                        for cfg in Debug Release; do
152                            open_tag FileConfiguration \
153                                Name="${cfg}|${plat}" \
154
155                            tag Tool \
156                                Name="VCCustomBuildTool" \
157                                Description="Assembling \$(InputFileName)" \
158                                CommandLine="$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)\\$objf" \
159                                Outputs="\$(IntDir)\\$objf" \
160
161                            close_tag FileConfiguration
162                        done
163                    done
164                fi
165                if [ "$pat" == "c" ] || \
166                   [ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then
167                    for plat in "${platforms[@]}"; do
168                        for cfg in Debug Release; do
169                            open_tag FileConfiguration \
170                                Name="${cfg}|${plat}" \
171
172                            tag Tool \
173                                Name="VCCLCompilerTool" \
174                                ObjectFile="\$(IntDir)\\$objf" \
175
176                            close_tag FileConfiguration
177                        done
178                    done
179                fi
180                close_tag File
181
182                break
183            fi
184        done
185    done
186
187    close_tag Filter
188    IFS="$saveIFS"
189}
190
191# Process command line
192unset target
193for opt in "$@"; do
194    optval="${opt#*=}"
195    case "$opt" in
196        --help|-h) show_help
197        ;;
198        --target=*) target="${optval}"
199        ;;
200        --out=*) outfile="$optval"
201        ;;
202        --name=*) name="${optval}"
203        ;;
204        --proj-guid=*) guid="${optval}"
205        ;;
206        --module-def=*) link_opts="${link_opts} ModuleDefinitionFile=${optval}"
207        ;;
208        --exe) proj_kind="exe"
209        ;;
210        --dll) proj_kind="dll"
211        ;;
212        --lib) proj_kind="lib"
213        ;;
214        --src-path-bare=*) src_path_bare="$optval"
215        ;;
216        --static-crt) use_static_runtime=true
217        ;;
218        --ver=*)
219            vs_ver="$optval"
220            case "$optval" in
221                [789])
222                ;;
223                *) die Unrecognized Visual Studio Version in $opt
224                ;;
225            esac
226        ;;
227        -I*)
228            opt="${opt%/}"
229            incs="${incs}${incs:+;}&quot;${opt##-I}&quot;"
230            yasmincs="${yasmincs} ${opt}"
231        ;;
232        -D*) defines="${defines}${defines:+;}${opt##-D}"
233        ;;
234        -L*) # fudge . to $(OutDir)
235            if [ "${opt##-L}" == "." ]; then
236                libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
237            else
238                 # Also try directories for this platform/configuration
239                 libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}&quot;"
240                 libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}/\$(PlatformName)/\$(ConfigurationName)&quot;"
241                 libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}/\$(PlatformName)&quot;"
242            fi
243        ;;
244        -l*) libs="${libs}${libs:+ }${opt##-l}.lib"
245        ;;
246        -*) die_unknown $opt
247        ;;
248        *)
249            file_list[${#file_list[@]}]="$opt"
250            case "$opt" in
251                 *.asm) uses_asm=true
252                 ;;
253            esac
254        ;;
255    esac
256done
257outfile=${outfile:-/dev/stdout}
258guid=${guid:-`generate_uuid`}
259asm_use_custom_step=false
260uses_asm=${uses_asm:-false}
261case "${vs_ver:-8}" in
262    7) vs_ver_id="7.10"
263       asm_use_custom_step=$uses_asm
264       warn_64bit='Detect64BitPortabilityProblems=true'
265    ;;
266    8) vs_ver_id="8.00"
267       asm_use_custom_step=$uses_asm
268       warn_64bit='Detect64BitPortabilityProblems=true'
269    ;;
270    9) vs_ver_id="9.00"
271       asm_use_custom_step=$uses_asm
272       warn_64bit='Detect64BitPortabilityProblems=false'
273    ;;
274esac
275
276[ -n "$name" ] || die "Project name (--name) must be specified!"
277[ -n "$target" ] || die "Target (--target) must be specified!"
278
279if ${use_static_runtime:-false}; then
280    release_runtime=0
281    debug_runtime=1
282    lib_sfx=mt
283else
284    release_runtime=2
285    debug_runtime=3
286    lib_sfx=md
287fi
288
289# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
290# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
291# debug exe, so this may need to be refactored later.
292for lib in ${libs}; do
293    if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
294        lib=${lib%.lib}d.lib
295    fi
296    debug_libs="${debug_libs}${debug_libs:+ }${lib}"
297done
298
299
300# List Keyword for this target
301case "$target" in
302    x86*) keyword="ManagedCProj"
303    ;;
304    *) die "Unsupported target $target!"
305esac
306
307# List of all platforms supported for this target
308case "$target" in
309    x86_64*)
310        platforms[0]="x64"
311        asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
312        asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
313    ;;
314    x86*)
315        platforms[0]="Win32"
316        asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
317        asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
318    ;;
319    *) die "Unsupported target $target!"
320    ;;
321esac
322
323generate_vcproj() {
324    case "$proj_kind" in
325        exe) vs_ConfigurationType=1
326        ;;
327        dll) vs_ConfigurationType=2
328        ;;
329        *)   vs_ConfigurationType=4
330        ;;
331    esac
332
333    echo "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
334    open_tag VisualStudioProject \
335        ProjectType="Visual C++" \
336        Version="${vs_ver_id}" \
337        Name="${name}" \
338        ProjectGUID="{${guid}}" \
339        RootNamespace="${name}" \
340        Keyword="${keyword}" \
341
342    open_tag Platforms
343    for plat in "${platforms[@]}"; do
344        tag Platform Name="$plat"
345    done
346    close_tag Platforms
347
348    open_tag Configurations
349    for plat in "${platforms[@]}"; do
350        plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
351        open_tag Configuration \
352            Name="Debug|$plat" \
353            OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
354            IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
355            ConfigurationType="$vs_ConfigurationType" \
356            CharacterSet="1" \
357
358        case "$target" in
359            x86*)
360                case "$name" in
361                    obj_int_extract)
362                        tag Tool \
363                            Name="VCCLCompilerTool" \
364                            Optimization="0" \
365                            AdditionalIncludeDirectories="$incs" \
366                            PreprocessorDefinitions="WIN32;DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
367                            RuntimeLibrary="$debug_runtime" \
368                            WarningLevel="3" \
369                            DebugInformationFormat="1" \
370                            $warn_64bit \
371                    ;;
372                    vpx)
373                        tag Tool \
374                            Name="VCPreBuildEventTool" \
375                            CommandLine="call obj_int_extract.bat $src_path_bare $plat_no_ws\\\$(ConfigurationName)" \
376
377                        tag Tool \
378                            Name="VCCLCompilerTool" \
379                            Optimization="0" \
380                            AdditionalIncludeDirectories="$incs" \
381                            PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
382                            RuntimeLibrary="$debug_runtime" \
383                            UsePrecompiledHeader="0" \
384                            WarningLevel="3" \
385                            DebugInformationFormat="2" \
386                            $warn_64bit \
387
388                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs" Debug="true"
389                    ;;
390                    *)
391                        tag Tool \
392                            Name="VCCLCompilerTool" \
393                            Optimization="0" \
394                            AdditionalIncludeDirectories="$incs" \
395                            PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
396                            RuntimeLibrary="$debug_runtime" \
397                            UsePrecompiledHeader="0" \
398                            WarningLevel="3" \
399                            DebugInformationFormat="2" \
400                            $warn_64bit \
401
402                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs" Debug="true"
403                    ;;
404                esac
405            ;;
406        esac
407
408        case "$proj_kind" in
409            exe)
410                case "$target" in
411                    x86*)
412                        case "$name" in
413                            obj_int_extract)
414                                tag Tool \
415                                    Name="VCLinkerTool" \
416                                    GenerateDebugInformation="true" \
417                            ;;
418                            *)
419                                tag Tool \
420                                    Name="VCLinkerTool" \
421                                    AdditionalDependencies="$debug_libs \$(NoInherit)" \
422                                    AdditionalLibraryDirectories="$libdirs" \
423                                    GenerateDebugInformation="true" \
424                                    ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \
425                            ;;
426                        esac
427                    ;;
428                 esac
429            ;;
430            lib)
431                case "$target" in
432                    x86*)
433                        tag Tool \
434                            Name="VCLibrarianTool" \
435                            OutputFile="\$(OutDir)/${name}${lib_sfx}d.lib" \
436
437                    ;;
438                esac
439            ;;
440            dll)
441                tag Tool \
442                    Name="VCLinkerTool" \
443                    AdditionalDependencies="\$(NoInherit)" \
444                    LinkIncremental="2" \
445                    GenerateDebugInformation="true" \
446                    AssemblyDebug="1" \
447                    TargetMachine="1" \
448                    $link_opts \
449
450            ;;
451        esac
452
453        close_tag Configuration
454
455        open_tag Configuration \
456            Name="Release|$plat" \
457            OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
458            IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
459            ConfigurationType="$vs_ConfigurationType" \
460            CharacterSet="1" \
461            WholeProgramOptimization="0" \
462
463        case "$target" in
464            x86*)
465                case "$name" in
466                    obj_int_extract)
467                        tag Tool \
468                            Name="VCCLCompilerTool" \
469                            Optimization="2" \
470                            FavorSizeorSpeed="1" \
471                            AdditionalIncludeDirectories="$incs" \
472                            PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
473                            RuntimeLibrary="$release_runtime" \
474                            UsePrecompiledHeader="0" \
475                            WarningLevel="3" \
476                            DebugInformationFormat="0" \
477                            $warn_64bit \
478                    ;;
479                    vpx)
480                        tag Tool \
481                            Name="VCPreBuildEventTool" \
482                            CommandLine="call obj_int_extract.bat $src_path_bare $plat_no_ws\\\$(ConfigurationName)" \
483
484                        tag Tool \
485                            Name="VCCLCompilerTool" \
486                            Optimization="2" \
487                            FavorSizeorSpeed="1" \
488                            AdditionalIncludeDirectories="$incs" \
489                            PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
490                            RuntimeLibrary="$release_runtime" \
491                            UsePrecompiledHeader="0" \
492                            WarningLevel="3" \
493                            DebugInformationFormat="0" \
494                            $warn_64bit \
495
496                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs"
497                    ;;
498                    *)
499                        tag Tool \
500                            Name="VCCLCompilerTool" \
501                            AdditionalIncludeDirectories="$incs" \
502                            Optimization="2" \
503                            FavorSizeorSpeed="1" \
504                            PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
505                            RuntimeLibrary="$release_runtime" \
506                            UsePrecompiledHeader="0" \
507                            WarningLevel="3" \
508                            DebugInformationFormat="0" \
509                            $warn_64bit \
510
511                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs"
512                    ;;
513                esac
514            ;;
515        esac
516
517        case "$proj_kind" in
518            exe)
519                case "$target" in
520                    x86*)
521                        case "$name" in
522                            obj_int_extract)
523                                tag Tool \
524                                    Name="VCLinkerTool" \
525                                    GenerateDebugInformation="true" \
526                            ;;
527                            *)
528                                tag Tool \
529                                    Name="VCLinkerTool" \
530                                    AdditionalDependencies="$libs \$(NoInherit)" \
531                                    AdditionalLibraryDirectories="$libdirs" \
532
533                            ;;
534                        esac
535                    ;;
536                 esac
537            ;;
538            lib)
539                case "$target" in
540                    x86*)
541                        tag Tool \
542                            Name="VCLibrarianTool" \
543                            OutputFile="\$(OutDir)/${name}${lib_sfx}.lib" \
544
545                    ;;
546                esac
547            ;;
548            dll) # note differences to debug version: LinkIncremental, AssemblyDebug
549                tag Tool \
550                    Name="VCLinkerTool" \
551                    AdditionalDependencies="\$(NoInherit)" \
552                    LinkIncremental="1" \
553                    GenerateDebugInformation="true" \
554                    TargetMachine="1" \
555                    $link_opts \
556
557            ;;
558        esac
559
560        close_tag Configuration
561    done
562    close_tag Configurations
563
564    open_tag Files
565    generate_filter srcs   "Source Files"   "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx"
566    generate_filter hdrs   "Header Files"   "h;hm;inl;inc;xsd"
567    generate_filter resrcs "Resource Files" "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
568    generate_filter resrcs "Build Files"    "mk"
569    close_tag Files
570
571    tag       Globals
572    close_tag VisualStudioProject
573
574    # This must be done from within the {} subshell
575    echo "Ignored files list (${#file_list[@]} items) is:" >&2
576    for f in "${file_list[@]}"; do
577        echo "    $f" >&2
578    done
579}
580
581generate_vcproj |
582    sed  -e '/"/s;\([^ "]\)/;\1\\;g' > ${outfile}
583
584exit
585<!--
586TODO: Add any files not captured by filters.
587                <File
588                        RelativePath=".\ReadMe.txt"
589                        >
590                </File>
591-->
592