Home | History | Annotate | Download | only in make
      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 
     12 self=$0
     13 self_basename=${self##*/}
     14 self_dirname=$(dirname "$0")
     15 
     16 . "$self_dirname/msvs_common.sh"|| exit 127
     17 
     18 show_help() {
     19     cat <<EOF
     20 Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
     21 
     22 This script generates a Visual Studio project file from a list of source
     23 code files.
     24 
     25 Options:
     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 (10,11,12,14,15) 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
     43 EOF
     44     exit 1
     45 }
     46 
     47 tag_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 
     63 generate_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" ]) && $asm_use_custom_step; 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
    138 unset target
    139 for opt in "$@"; do
    140     optval="${opt#*=}"
    141     case "$opt" in
    142         --help|-h) show_help
    143         ;;
    144         --target=*) target="${optval}"
    145         ;;
    146         --out=*) outfile="$optval"
    147         ;;
    148         --name=*) name="${optval}"
    149         ;;
    150         --proj-guid=*) guid="${optval}"
    151         ;;
    152         --module-def=*) module_def="${optval}"
    153         ;;
    154         --exe) proj_kind="exe"
    155         ;;
    156         --dll) proj_kind="dll"
    157         ;;
    158         --lib) proj_kind="lib"
    159         ;;
    160         --src-path-bare=*)
    161             src_path_bare=$(fix_path "$optval")
    162             src_path_bare=${src_path_bare%/}
    163         ;;
    164         --static-crt) use_static_runtime=true
    165         ;;
    166         --enable-werror) werror=true
    167         ;;
    168         --ver=*)
    169             vs_ver="$optval"
    170             case "$optval" in
    171                 10|11|12|14|15)
    172                 ;;
    173                 *) die Unrecognized Visual Studio Version in $opt
    174                 ;;
    175             esac
    176         ;;
    177         -I*)
    178             opt=${opt##-I}
    179             opt=$(fix_path "$opt")
    180             opt="${opt%/}"
    181             incs="${incs}${incs:+;}&quot;${opt}&quot;"
    182             yasmincs="${yasmincs} -I&quot;${opt}&quot;"
    183         ;;
    184         -D*) defines="${defines}${defines:+;}${opt##-D}"
    185         ;;
    186         -L*) # fudge . to $(OutDir)
    187             if [ "${opt##-L}" == "." ]; then
    188                 libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
    189             else
    190                  # Also try directories for this platform/configuration
    191                  opt=${opt##-L}
    192                  opt=$(fix_path "$opt")
    193                  libdirs="${libdirs}${libdirs:+;}&quot;${opt}&quot;"
    194                  libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)/\$(Configuration)&quot;"
    195                  libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)&quot;"
    196             fi
    197         ;;
    198         -l*) libs="${libs}${libs:+ }${opt##-l}.lib"
    199         ;;
    200         -*) die_unknown $opt
    201         ;;
    202         *)
    203             # The paths in file_list are fixed outside of the loop.
    204             file_list[${#file_list[@]}]="$opt"
    205             case "$opt" in
    206                  *.asm|*.[Ss]) uses_asm=true
    207                  ;;
    208             esac
    209         ;;
    210     esac
    211 done
    212 
    213 # Make one call to fix_path for file_list to improve performance.
    214 fix_file_list file_list
    215 
    216 outfile=${outfile:-/dev/stdout}
    217 guid=${guid:-`generate_uuid`}
    218 asm_use_custom_step=false
    219 uses_asm=${uses_asm:-false}
    220 case "${vs_ver:-11}" in
    221     10|11|12|14|15)
    222        asm_use_custom_step=$uses_asm
    223     ;;
    224 esac
    225 
    226 [ -n "$name" ] || die "Project name (--name) must be specified!"
    227 [ -n "$target" ] || die "Target (--target) must be specified!"
    228 
    229 if ${use_static_runtime:-false}; then
    230     release_runtime=MultiThreaded
    231     debug_runtime=MultiThreadedDebug
    232     lib_sfx=mt
    233 else
    234     release_runtime=MultiThreadedDLL
    235     debug_runtime=MultiThreadedDebugDLL
    236     lib_sfx=md
    237 fi
    238 
    239 # Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
    240 # it to ${lib_sfx}d.lib. This precludes linking to release libs from a
    241 # debug exe, so this may need to be refactored later.
    242 for lib in ${libs}; do
    243     if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
    244         lib=${lib%.lib}d.lib
    245     fi
    246     debug_libs="${debug_libs}${debug_libs:+ }${lib}"
    247 done
    248 debug_libs=${debug_libs// /;}
    249 libs=${libs// /;}
    250 
    251 
    252 # List of all platforms supported for this target
    253 case "$target" in
    254     x86_64*)
    255         platforms[0]="x64"
    256         asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} &quot;%(FullPath)&quot;"
    257         asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} &quot;%(FullPath)&quot;"
    258     ;;
    259     x86*)
    260         platforms[0]="Win32"
    261         asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} &quot;%(FullPath)&quot;"
    262         asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} &quot;%(FullPath)&quot;"
    263     ;;
    264     arm*)
    265         platforms[0]="ARM"
    266         asm_Debug_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
    267         asm_Release_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
    268     ;;
    269     *) die "Unsupported target $target!"
    270     ;;
    271 esac
    272 
    273 generate_vcxproj() {
    274     echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
    275     open_tag Project \
    276         DefaultTargets="Build" \
    277         ToolsVersion="4.0" \
    278         xmlns="http://schemas.microsoft.com/developer/msbuild/2003" \
    279 
    280     open_tag ItemGroup \
    281         Label="ProjectConfigurations"
    282     for plat in "${platforms[@]}"; do
    283         for config in Debug Release; do
    284             open_tag ProjectConfiguration \
    285                 Include="$config|$plat"
    286             tag_content Configuration $config
    287             tag_content Platform $plat
    288             close_tag ProjectConfiguration
    289         done
    290     done
    291     close_tag ItemGroup
    292 
    293     open_tag PropertyGroup \
    294         Label="Globals"
    295         tag_content ProjectGuid "{${guid}}"
    296         tag_content RootNamespace ${name}
    297         tag_content Keyword ManagedCProj
    298         if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then
    299             tag_content AppContainerApplication true
    300             # The application type can be one of "Windows Store",
    301             # "Windows Phone" or "Windows Phone Silverlight". The
    302             # actual value doesn't matter from the libvpx point of view,
    303             # since a static library built for one works on the others.
    304             # The PlatformToolset field needs to be set in sync with this;
    305             # for Windows Store and Windows Phone Silverlight it should be
    306             # v120 while it should be v120_wp81 if the type is Windows Phone.
    307             tag_content ApplicationType "Windows Store"
    308             tag_content ApplicationTypeRevision 8.1
    309         fi
    310     close_tag PropertyGroup
    311 
    312     tag Import \
    313         Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
    314 
    315     for plat in "${platforms[@]}"; do
    316         for config in Release Debug; do
    317             open_tag PropertyGroup \
    318                 Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \
    319                 Label="Configuration"
    320             if [ "$proj_kind" = "exe" ]; then
    321                 tag_content ConfigurationType Application
    322             elif [ "$proj_kind" = "dll" ]; then
    323                 tag_content ConfigurationType DynamicLibrary
    324             else
    325                 tag_content ConfigurationType StaticLibrary
    326             fi
    327             if [ "$vs_ver" = "11" ]; then
    328                 if [ "$plat" = "ARM" ]; then
    329                     # Setting the wp80 toolchain automatically sets the
    330                     # WINAPI_FAMILY define, which is required for building
    331                     # code for arm with the windows headers. Alternatively,
    332                     # one could add AppContainerApplication=true in the Globals
    333                     # section and add PrecompiledHeader=NotUsing and
    334                     # CompileAsWinRT=false in ClCompile and SubSystem=Console
    335                     # in Link.
    336                     tag_content PlatformToolset v110_wp80
    337                 else
    338                     tag_content PlatformToolset v110
    339                 fi
    340             fi
    341             if [ "$vs_ver" = "12" ]; then
    342                 # Setting a PlatformToolset indicating windows phone isn't
    343                 # enough to build code for arm with MSVC 2013, one strictly
    344                 # has to enable AppContainerApplication as well.
    345                 tag_content PlatformToolset v120
    346             fi
    347             if [ "$vs_ver" = "14" ]; then
    348                 tag_content PlatformToolset v140
    349             fi
    350             if [ "$vs_ver" = "15" ]; then
    351                 tag_content PlatformToolset v141
    352             fi
    353             tag_content CharacterSet Unicode
    354             if [ "$config" = "Release" ]; then
    355                 tag_content WholeProgramOptimization true
    356             fi
    357             close_tag PropertyGroup
    358         done
    359     done
    360 
    361     tag Import \
    362         Project="\$(VCTargetsPath)\\Microsoft.Cpp.props"
    363 
    364     open_tag ImportGroup \
    365         Label="PropertySheets"
    366         tag Import \
    367             Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" \
    368             Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" \
    369             Label="LocalAppDataPlatform"
    370     close_tag ImportGroup
    371 
    372     tag PropertyGroup \
    373         Label="UserMacros"
    374 
    375     for plat in "${platforms[@]}"; do
    376         plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
    377         for config in Debug Release; do
    378             open_tag PropertyGroup \
    379                 Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
    380             tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\"
    381             tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\"
    382             if [ "$proj_kind" == "lib" ]; then
    383               if [ "$config" == "Debug" ]; then
    384                 config_suffix=d
    385               else
    386                 config_suffix=""
    387               fi
    388               tag_content TargetName "${name}${lib_sfx}${config_suffix}"
    389             fi
    390             close_tag PropertyGroup
    391         done
    392     done
    393 
    394     for plat in "${platforms[@]}"; do
    395         for config in Debug Release; do
    396             open_tag ItemDefinitionGroup \
    397                 Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
    398             if [ "$name" == "vpx" ]; then
    399                 hostplat=$plat
    400                 if [ "$hostplat" == "ARM" ]; then
    401                     hostplat=Win32
    402                 fi
    403             fi
    404             open_tag ClCompile
    405             if [ "$config" = "Debug" ]; then
    406                 opt=Disabled
    407                 runtime=$debug_runtime
    408                 curlibs=$debug_libs
    409                 debug=_DEBUG
    410             else
    411                 opt=MaxSpeed
    412                 runtime=$release_runtime
    413                 curlibs=$libs
    414                 tag_content FavorSizeOrSpeed Speed
    415                 debug=NDEBUG
    416             fi
    417             extradefines=";$defines"
    418             tag_content Optimization $opt
    419             tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)"
    420             tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)"
    421             tag_content RuntimeLibrary $runtime
    422             tag_content WarningLevel Level3
    423             if ${werror:-false}; then
    424                 tag_content TreatWarningAsError true
    425             fi
    426             if [ $vs_ver -ge 11 ]; then
    427                 # We need to override the defaults for these settings
    428                 # if AppContainerApplication is set.
    429                 tag_content CompileAsWinRT false
    430                 tag_content PrecompiledHeader NotUsing
    431                 tag_content SDLCheck false
    432             fi
    433             close_tag ClCompile
    434             case "$proj_kind" in
    435             exe)
    436                 open_tag Link
    437                 tag_content GenerateDebugInformation true
    438                 # Console is the default normally, but if
    439                 # AppContainerApplication is set, we need to override it.
    440                 tag_content SubSystem Console
    441                 close_tag Link
    442                 ;;
    443             dll)
    444                 open_tag Link
    445                 tag_content GenerateDebugInformation true
    446                 tag_content ModuleDefinitionFile $module_def
    447                 close_tag Link
    448                 ;;
    449             lib)
    450                 ;;
    451             esac
    452             close_tag ItemDefinitionGroup
    453         done
    454 
    455     done
    456 
    457     open_tag ItemGroup
    458     generate_filter "Source Files"   "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s;S"
    459     close_tag ItemGroup
    460     open_tag ItemGroup
    461     generate_filter "Header Files"   "h;hm;inl;inc;xsd"
    462     close_tag ItemGroup
    463     open_tag ItemGroup
    464     generate_filter "Build Files"    "mk"
    465     close_tag ItemGroup
    466     open_tag ItemGroup
    467     generate_filter "References"     "vcxproj"
    468     close_tag ItemGroup
    469 
    470     tag Import \
    471         Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets"
    472 
    473     open_tag ImportGroup \
    474         Label="ExtensionTargets"
    475     close_tag ImportGroup
    476 
    477     close_tag Project
    478 
    479     # This must be done from within the {} subshell
    480     echo "Ignored files list (${#file_list[@]} items) is:" >&2
    481     for f in "${file_list[@]}"; do
    482         echo "    $f" >&2
    483     done
    484 }
    485 
    486 # This regexp doesn't catch most of the strings in the vcxproj format,
    487 # since they're like <tag>path</tag> instead of <tag attr="path" />
    488 # as previously. It still seems to work ok despite this.
    489 generate_vcxproj |
    490     sed  -e '/"/s;\([^ "]\)/;\1\\;g' |
    491     sed  -e '/xmlns/s;\\;/;g' > ${outfile}
    492 
    493 exit
    494