gen_msvs_vcxproj.sh 18 KB

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