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 (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 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" ]) && $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 138unset target 139for 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:+;}"${opt}"" 182 yasmincs="${yasmincs} -I"${opt}"" 183 ;; 184 -D*) defines="${defines}${defines:+;}${opt##-D}" 185 ;; 186 -L*) # fudge . to $(OutDir) 187 if [ "${opt##-L}" == "." ]; then 188 libdirs="${libdirs}${libdirs:+;}"\$(OutDir)"" 189 else 190 # Also try directories for this platform/configuration 191 opt=${opt##-L} 192 opt=$(fix_path "$opt") 193 libdirs="${libdirs}${libdirs:+;}"${opt}"" 194 libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)/\$(Configuration)"" 195 libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)"" 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 211done 212 213# Make one call to fix_path for file_list to improve performance. 214fix_file_list file_list 215 216outfile=${outfile:-/dev/stdout} 217guid=${guid:-`generate_uuid`} 218asm_use_custom_step=false 219uses_asm=${uses_asm:-false} 220case "${vs_ver:-11}" in 221 10|11|12|14|15) 222 asm_use_custom_step=$uses_asm 223 ;; 224esac 225 226[ -n "$name" ] || die "Project name (--name) must be specified!" 227[ -n "$target" ] || die "Target (--target) must be specified!" 228 229if ${use_static_runtime:-false}; then 230 release_runtime=MultiThreaded 231 debug_runtime=MultiThreadedDebug 232 lib_sfx=mt 233else 234 release_runtime=MultiThreadedDLL 235 debug_runtime=MultiThreadedDebugDLL 236 lib_sfx=md 237fi 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. 242for 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}" 247done 248debug_libs=${debug_libs// /;} 249libs=${libs// /;} 250 251 252# List of all platforms supported for this target 253case "$target" in 254 x86_64*) 255 platforms[0]="x64" 256 asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} "%(FullPath)"" 257 asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} "%(FullPath)"" 258 ;; 259 x86*) 260 platforms[0]="Win32" 261 asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} "%(FullPath)"" 262 asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} "%(FullPath)"" 263 ;; 264 arm64*) 265 platforms[0]="ARM64" 266 asm_Debug_cmdline="armasm64 -nologo -oldit "%(FullPath)"" 267 asm_Release_cmdline="armasm64 -nologo -oldit "%(FullPath)"" 268 ;; 269 arm*) 270 platforms[0]="ARM" 271 asm_Debug_cmdline="armasm -nologo -oldit "%(FullPath)"" 272 asm_Release_cmdline="armasm -nologo -oldit "%(FullPath)"" 273 ;; 274 *) die "Unsupported target $target!" 275 ;; 276esac 277 278generate_vcxproj() { 279 echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" 280 open_tag Project \ 281 DefaultTargets="Build" \ 282 ToolsVersion="4.0" \ 283 xmlns="http://schemas.microsoft.com/developer/msbuild/2003" \ 284 285 open_tag ItemGroup \ 286 Label="ProjectConfigurations" 287 for plat in "${platforms[@]}"; do 288 for config in Debug Release; do 289 open_tag ProjectConfiguration \ 290 Include="$config|$plat" 291 tag_content Configuration $config 292 tag_content Platform $plat 293 close_tag ProjectConfiguration 294 done 295 done 296 close_tag ItemGroup 297 298 open_tag PropertyGroup \ 299 Label="Globals" 300 tag_content ProjectGuid "{${guid}}" 301 tag_content RootNamespace ${name} 302 tag_content Keyword ManagedCProj 303 if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then 304 tag_content AppContainerApplication true 305 # The application type can be one of "Windows Store", 306 # "Windows Phone" or "Windows Phone Silverlight". The 307 # actual value doesn't matter from the libvpx point of view, 308 # since a static library built for one works on the others. 309 # The PlatformToolset field needs to be set in sync with this; 310 # for Windows Store and Windows Phone Silverlight it should be 311 # v120 while it should be v120_wp81 if the type is Windows Phone. 312 tag_content ApplicationType "Windows Store" 313 tag_content ApplicationTypeRevision 8.1 314 fi 315 if [ $vs_ver -eq 15 ] && [ "${platforms[0]}" = "ARM64" ]; then 316 # Require the first Visual Studio version to have ARM64 support. 317 tag_content MinimumVisualStudioVersion 15.9 318 # Require a Windows SDK that has ARM64 support rather than the 319 # default of 8.1. 320 # Since VS 15 does not have a 'use latest SDK version' facility, 321 # set WindowsTargetPlatformVersion to the first official SDK 322 # version to have ARM64 support. 323 tag_content WindowsTargetPlatformVersion 10.0.17134.0 324 fi 325 close_tag PropertyGroup 326 327 tag Import \ 328 Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" 329 330 for plat in "${platforms[@]}"; do 331 for config in Release Debug; do 332 open_tag PropertyGroup \ 333 Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \ 334 Label="Configuration" 335 if [ "$proj_kind" = "exe" ]; then 336 tag_content ConfigurationType Application 337 elif [ "$proj_kind" = "dll" ]; then 338 tag_content ConfigurationType DynamicLibrary 339 else 340 tag_content ConfigurationType StaticLibrary 341 fi 342 if [ "$vs_ver" = "11" ]; then 343 if [ "$plat" = "ARM" ]; then 344 # Setting the wp80 toolchain automatically sets the 345 # WINAPI_FAMILY define, which is required for building 346 # code for arm with the windows headers. Alternatively, 347 # one could add AppContainerApplication=true in the Globals 348 # section and add PrecompiledHeader=NotUsing and 349 # CompileAsWinRT=false in ClCompile and SubSystem=Console 350 # in Link. 351 tag_content PlatformToolset v110_wp80 352 else 353 tag_content PlatformToolset v110 354 fi 355 fi 356 if [ "$vs_ver" = "12" ]; then 357 # Setting a PlatformToolset indicating windows phone isn't 358 # enough to build code for arm with MSVC 2013, one strictly 359 # has to enable AppContainerApplication as well. 360 tag_content PlatformToolset v120 361 fi 362 if [ "$vs_ver" = "14" ]; then 363 tag_content PlatformToolset v140 364 fi 365 if [ "$vs_ver" = "15" ]; then 366 tag_content PlatformToolset v141 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