| #!/bin/bash | |
| ## Copyright (c) 2016, Alliance for Open Media. All rights reserved | |
| ## | |
| ## This source code is subject to the terms of the BSD 2 Clause License and | |
| ## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | |
| ## was not distributed with this source code in the LICENSE file, you can | |
| ## obtain it at www.aomedia.org/license/software. If the Alliance for Open | |
| ## Media Patent License 1.0 was not distributed with this source code in the | |
| ## PATENTS file, you can obtain it at www.aomedia.org/license/patent. | |
| ## | |
| self=$0 | |
| self_basename=${self##*/} | |
| self_dirname=$(dirname "$0") | |
| . "$self_dirname/msvs_common.sh"|| exit 127 | |
| show_help() { | |
| cat <<EOF | |
| Usage: ${self_basename} --name=projname [options] file1 [file2 ...] | |
| This script generates a Visual Studio project file from a list of source | |
| code files. | |
| Options: | |
| --help Print this message | |
| --exe Generate a project for building an Application | |
| --lib Generate a project for creating a static library | |
| --dll Generate a project for creating a dll | |
| --static-crt Use the static C runtime (/MT) | |
| --enable-werror Treat warnings as errors (/WX) | |
| --target=isa-os-cc Target specifier (required) | |
| --out=filename Write output to a file [stdout] | |
| --name=project_name Name of the project (required) | |
| --proj-guid=GUID GUID to use for the project | |
| --module-def=filename File containing export definitions (for DLLs) | |
| --ver=version Version (10,11,12,14) of visual studio to generate for | |
| --src-path-bare=dir Path to root of source tree | |
| -Ipath/to/include Additional include directories | |
| -DFLAG[=value] Preprocessor macros to define | |
| -Lpath/to/lib Additional library search paths | |
| -llibname Library to link against | |
| EOF | |
| exit 1 | |
| } | |
| tag_content() { | |
| local tag=$1 | |
| local content=$2 | |
| shift | |
| shift | |
| if [ $# -ne 0 ]; then | |
| echo "${indent}<${tag}" | |
| indent_push | |
| tag_attributes "$@" | |
| echo "${indent}>${content}</${tag}>" | |
| indent_pop | |
| else | |
| echo "${indent}<${tag}>${content}</${tag}>" | |
| fi | |
| } | |
| generate_filter() { | |
| local name=$1 | |
| local pats=$2 | |
| local file_list_sz | |
| local i | |
| local f | |
| local saveIFS="$IFS" | |
| local pack | |
| echo "generating filter '$name' from ${#file_list[@]} files" >&2 | |
| IFS=* | |
| file_list_sz=${#file_list[@]} | |
| for i in ${!file_list[@]}; do | |
| f=${file_list[i]} | |
| for pat in ${pats//;/$IFS}; do | |
| if [ "${f##*.}" == "$pat" ]; then | |
| unset file_list[i] | |
| objf=$(echo ${f%.*}.obj \ | |
| | sed -e "s,$src_path_bare,," \ | |
| -e 's/^[\./]\+//g' -e 's,[:/ ],_,g') | |
| if ([ "$pat" == "asm" ] || [ "$pat" == "s" ]) && $asm_use_custom_step; then | |
| # Avoid object file name collisions, i.e. aom_config.c and | |
| # aom_config.asm produce the same object file without | |
| # this additional suffix. | |
| objf=${objf%.obj}_asm.obj | |
| open_tag CustomBuild \ | |
| Include="$f" | |
| for plat in "${platforms[@]}"; do | |
| for cfg in Debug Release; do | |
| tag_content Message "Assembling %(Filename)%(Extension)" \ | |
| Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'" | |
| tag_content Command "$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)$objf" \ | |
| Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'" | |
| tag_content Outputs "\$(IntDir)$objf" \ | |
| Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'" | |
| done | |
| done | |
| close_tag CustomBuild | |
| elif [ "$pat" == "c" ] || \ | |
| [ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then | |
| open_tag ClCompile \ | |
| Include="$f" | |
| # Separate file names with Condition? | |
| tag_content ObjectFileName "\$(IntDir)$objf" | |
| # Check for AVX and turn it on to avoid warnings. | |
| if [[ $f =~ avx.?\.c$ ]]; then | |
| tag_content AdditionalOptions "/arch:AVX" | |
| fi | |
| close_tag ClCompile | |
| elif [ "$pat" == "h" ] ; then | |
| tag ClInclude \ | |
| Include="$f" | |
| elif [ "$pat" == "vcxproj" ] ; then | |
| open_tag ProjectReference \ | |
| Include="$f" | |
| depguid=`grep ProjectGuid "$f" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'` | |
| tag_content Project "$depguid" | |
| tag_content ReferenceOutputAssembly false | |
| close_tag ProjectReference | |
| else | |
| tag None \ | |
| Include="$f" | |
| fi | |
| break | |
| fi | |
| done | |
| done | |
| IFS="$saveIFS" | |
| } | |
| # Process command line | |
| unset target | |
| for opt in "$@"; do | |
| optval="${opt#*=}" | |
| case "$opt" in | |
| --help|-h) show_help | |
| ;; | |
| --target=*) target="${optval}" | |
| ;; | |
| --out=*) outfile="$optval" | |
| ;; | |
| --name=*) name="${optval}" | |
| ;; | |
| --proj-guid=*) guid="${optval}" | |
| ;; | |
| --module-def=*) module_def="${optval}" | |
| ;; | |
| --exe) proj_kind="exe" | |
| ;; | |
| --dll) proj_kind="dll" | |
| ;; | |
| --lib) proj_kind="lib" | |
| ;; | |
| --src-path-bare=*) | |
| src_path_bare=$(fix_path "$optval") | |
| src_path_bare=${src_path_bare%/} | |
| ;; | |
| --static-crt) use_static_runtime=true | |
| ;; | |
| --enable-werror) werror=true | |
| ;; | |
| --ver=*) | |
| vs_ver="$optval" | |
| case "$optval" in | |
| 10|11|12|14) | |
| ;; | |
| *) die Unrecognized Visual Studio Version in $opt | |
| ;; | |
| esac | |
| ;; | |
| -I*) | |
| opt=${opt##-I} | |
| opt=$(fix_path "$opt") | |
| opt="${opt%/}" | |
| incs="${incs}${incs:+;}"${opt}"" | |
| yasmincs="${yasmincs} -I"${opt}"" | |
| ;; | |
| -D*) defines="${defines}${defines:+;}${opt##-D}" | |
| ;; | |
| -L*) # fudge . to $(OutDir) | |
| if [ "${opt##-L}" == "." ]; then | |
| libdirs="${libdirs}${libdirs:+;}"\$(OutDir)"" | |
| else | |
| # Also try directories for this platform/configuration | |
| opt=${opt##-L} | |
| opt=$(fix_path "$opt") | |
| libdirs="${libdirs}${libdirs:+;}"${opt}"" | |
| libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)/\$(Configuration)"" | |
| libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)"" | |
| fi | |
| ;; | |
| -l*) libs="${libs}${libs:+ }${opt##-l}.lib" | |
| ;; | |
| -*) die_unknown $opt | |
| ;; | |
| *) | |
| # The paths in file_list are fixed outside of the loop. | |
| file_list[${#file_list[@]}]="$opt" | |
| case "$opt" in | |
| *.asm|*.s) uses_asm=true | |
| ;; | |
| esac | |
| ;; | |
| esac | |
| done | |
| # Make one call to fix_path for file_list to improve performance. | |
| fix_file_list file_list | |
| outfile=${outfile:-/dev/stdout} | |
| guid=${guid:-`generate_uuid`} | |
| asm_use_custom_step=false | |
| uses_asm=${uses_asm:-false} | |
| case "${vs_ver:-11}" in | |
| 10|11|12|14) | |
| asm_use_custom_step=$uses_asm | |
| ;; | |
| esac | |
| [ -n "$name" ] || die "Project name (--name) must be specified!" | |
| [ -n "$target" ] || die "Target (--target) must be specified!" | |
| if ${use_static_runtime:-false}; then | |
| release_runtime=MultiThreaded | |
| debug_runtime=MultiThreadedDebug | |
| lib_sfx=mt | |
| else | |
| release_runtime=MultiThreadedDLL | |
| debug_runtime=MultiThreadedDebugDLL | |
| lib_sfx=md | |
| fi | |
| # Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename | |
| # it to ${lib_sfx}d.lib. This precludes linking to release libs from a | |
| # debug exe, so this may need to be refactored later. | |
| for lib in ${libs}; do | |
| if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then | |
| lib=${lib%.lib}d.lib | |
| fi | |
| debug_libs="${debug_libs}${debug_libs:+ }${lib}" | |
| done | |
| debug_libs=${debug_libs// /;} | |
| libs=${libs// /;} | |
| # List of all platforms supported for this target | |
| case "$target" in | |
| x86_64*) | |
| platforms[0]="x64" | |
| asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} "%(FullPath)"" | |
| asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} "%(FullPath)"" | |
| ;; | |
| x86*) | |
| platforms[0]="Win32" | |
| asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} "%(FullPath)"" | |
| asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} "%(FullPath)"" | |
| ;; | |
| arm*) | |
| platforms[0]="ARM" | |
| asm_Debug_cmdline="armasm -nologo -oldit "%(FullPath)"" | |
| asm_Release_cmdline="armasm -nologo -oldit "%(FullPath)"" | |
| ;; | |
| *) die "Unsupported target $target!" | |
| ;; | |
| esac | |
| generate_vcxproj() { | |
| echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" | |
| open_tag Project \ | |
| DefaultTargets="Build" \ | |
| ToolsVersion="4.0" \ | |
| xmlns="http://schemas.microsoft.com/developer/msbuild/2003" \ | |
| open_tag ItemGroup \ | |
| Label="ProjectConfigurations" | |
| for plat in "${platforms[@]}"; do | |
| for config in Debug Release; do | |
| open_tag ProjectConfiguration \ | |
| Include="$config|$plat" | |
| tag_content Configuration $config | |
| tag_content Platform $plat | |
| close_tag ProjectConfiguration | |
| done | |
| done | |
| close_tag ItemGroup | |
| open_tag PropertyGroup \ | |
| Label="Globals" | |
| tag_content ProjectGuid "{${guid}}" | |
| tag_content RootNamespace ${name} | |
| tag_content Keyword ManagedCProj | |
| if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then | |
| tag_content AppContainerApplication true | |
| # The application type can be one of "Windows Store", | |
| # "Windows Phone" or "Windows Phone Silverlight". The | |
| # actual value doesn't matter from the libaom point of view, | |
| # since a static library built for one works on the others. | |
| # The PlatformToolset field needs to be set in sync with this; | |
| # for Windows Store and Windows Phone Silverlight it should be | |
| # v120 while it should be v120_wp81 if the type is Windows Phone. | |
| tag_content ApplicationType "Windows Store" | |
| tag_content ApplicationTypeRevision 8.1 | |
| fi | |
| close_tag PropertyGroup | |
| tag Import \ | |
| Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" | |
| for plat in "${platforms[@]}"; do | |
| for config in Release Debug; do | |
| open_tag PropertyGroup \ | |
| Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \ | |
| Label="Configuration" | |
| if [ "$proj_kind" = "exe" ]; then | |
| tag_content ConfigurationType Application | |
| elif [ "$proj_kind" = "dll" ]; then | |
| tag_content ConfigurationType DynamicLibrary | |
| else | |
| tag_content ConfigurationType StaticLibrary | |
| fi | |
| if [ "$vs_ver" = "11" ]; then | |
| if [ "$plat" = "ARM" ]; then | |
| # Setting the wp80 toolchain automatically sets the | |
| # WINAPI_FAMILY define, which is required for building | |
| # code for arm with the windows headers. Alternatively, | |
| # one could add AppContainerApplication=true in the Globals | |
| # section and add PrecompiledHeader=NotUsing and | |
| # CompileAsWinRT=false in ClCompile and SubSystem=Console | |
| # in Link. | |
| tag_content PlatformToolset v110_wp80 | |
| else | |
| tag_content PlatformToolset v110 | |
| fi | |
| fi | |
| if [ "$vs_ver" = "12" ]; then | |
| # Setting a PlatformToolset indicating windows phone isn't | |
| # enough to build code for arm with MSVC 2013, one strictly | |
| # has to enable AppContainerApplication as well. | |
| tag_content PlatformToolset v120 | |
| fi | |
| if [ "$vs_ver" = "14" ]; then | |
| tag_content PlatformToolset v140 | |
| fi | |
| tag_content CharacterSet Unicode | |
| if [ "$config" = "Release" ]; then | |
| tag_content WholeProgramOptimization true | |
| fi | |
| close_tag PropertyGroup | |
| done | |
| done | |
| tag Import \ | |
| Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" | |
| open_tag ImportGroup \ | |
| Label="PropertySheets" | |
| tag Import \ | |
| Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" \ | |
| Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" \ | |
| Label="LocalAppDataPlatform" | |
| close_tag ImportGroup | |
| tag PropertyGroup \ | |
| Label="UserMacros" | |
| for plat in "${platforms[@]}"; do | |
| plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'` | |
| for config in Debug Release; do | |
| open_tag PropertyGroup \ | |
| Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" | |
| tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\" | |
| tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\" | |
| if [ "$proj_kind" == "lib" ]; then | |
| if [ "$config" == "Debug" ]; then | |
| config_suffix=d | |
| else | |
| config_suffix="" | |
| fi | |
| tag_content TargetName "${name}${lib_sfx}${config_suffix}" | |
| fi | |
| close_tag PropertyGroup | |
| done | |
| done | |
| for plat in "${platforms[@]}"; do | |
| for config in Debug Release; do | |
| open_tag ItemDefinitionGroup \ | |
| Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" | |
| if [ "$name" == "aom" ]; then | |
| hostplat=$plat | |
| if [ "$hostplat" == "ARM" ]; then | |
| hostplat=Win32 | |
| fi | |
| fi | |
| open_tag ClCompile | |
| if [ "$config" = "Debug" ]; then | |
| opt=Disabled | |
| runtime=$debug_runtime | |
| curlibs=$debug_libs | |
| debug=_DEBUG | |
| else | |
| opt=MaxSpeed | |
| runtime=$release_runtime | |
| curlibs=$libs | |
| tag_content FavorSizeOrSpeed Speed | |
| debug=NDEBUG | |
| fi | |
| extradefines=";$defines" | |
| tag_content Optimization $opt | |
| tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)" | |
| tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)" | |
| tag_content RuntimeLibrary $runtime | |
| tag_content WarningLevel Level3 | |
| if ${werror:-false}; then | |
| tag_content TreatWarningAsError true | |
| fi | |
| if [ $vs_ver -ge 11 ]; then | |
| # We need to override the defaults for these settings | |
| # if AppContainerApplication is set. | |
| tag_content CompileAsWinRT false | |
| tag_content PrecompiledHeader NotUsing | |
| tag_content SDLCheck false | |
| fi | |
| close_tag ClCompile | |
| case "$proj_kind" in | |
| exe) | |
| open_tag Link | |
| tag_content GenerateDebugInformation true | |
| # Console is the default normally, but if | |
| # AppContainerApplication is set, we need to override it. | |
| tag_content SubSystem Console | |
| close_tag Link | |
| ;; | |
| dll) | |
| open_tag Link | |
| tag_content GenerateDebugInformation true | |
| tag_content ModuleDefinitionFile $module_def | |
| close_tag Link | |
| ;; | |
| lib) | |
| ;; | |
| esac | |
| close_tag ItemDefinitionGroup | |
| done | |
| done | |
| open_tag ItemGroup | |
| generate_filter "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s" | |
| close_tag ItemGroup | |
| open_tag ItemGroup | |
| generate_filter "Header Files" "h;hm;inl;inc;xsd" | |
| close_tag ItemGroup | |
| open_tag ItemGroup | |
| generate_filter "Build Files" "mk" | |
| close_tag ItemGroup | |
| open_tag ItemGroup | |
| generate_filter "References" "vcxproj" | |
| close_tag ItemGroup | |
| tag Import \ | |
| Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" | |
| open_tag ImportGroup \ | |
| Label="ExtensionTargets" | |
| close_tag ImportGroup | |
| close_tag Project | |
| # This must be done from within the {} subshell | |
| echo "Ignored files list (${#file_list[@]} items) is:" >&2 | |
| for f in "${file_list[@]}"; do | |
| echo " $f" >&2 | |
| done | |
| } | |
| # This regexp doesn't catch most of the strings in the vcxproj format, | |
| # since they're like <tag>path</tag> instead of <tag attr="path" /> | |
| # as previously. It still seems to work ok despite this. | |
| generate_vcxproj | | |
| sed -e '/"/s;\([^ "]\)/;\1\\;g' | | |
| sed -e '/xmlns/s;\\;/;g' > ${outfile} | |
| exit |