gen_msvs_vcxproj.sh 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  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. arm*)
  245. platforms[0]="ARM"
  246. asm_Debug_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
  247. asm_Release_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
  248. ;;
  249. *) die "Unsupported target $target!"
  250. ;;
  251. esac
  252. generate_vcxproj() {
  253. echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
  254. open_tag Project \
  255. DefaultTargets="Build" \
  256. ToolsVersion="4.0" \
  257. xmlns="http://schemas.microsoft.com/developer/msbuild/2003" \
  258. open_tag ItemGroup \
  259. Label="ProjectConfigurations"
  260. for plat in "${platforms[@]}"; do
  261. for config in Debug Release; do
  262. open_tag ProjectConfiguration \
  263. Include="$config|$plat"
  264. tag_content Configuration $config
  265. tag_content Platform $plat
  266. close_tag ProjectConfiguration
  267. done
  268. done
  269. close_tag ItemGroup
  270. open_tag PropertyGroup \
  271. Label="Globals"
  272. tag_content ProjectGuid "{${guid}}"
  273. tag_content RootNamespace ${name}
  274. tag_content Keyword ManagedCProj
  275. if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then
  276. tag_content AppContainerApplication true
  277. # The application type can be one of "Windows Store",
  278. # "Windows Phone" or "Windows Phone Silverlight". The
  279. # actual value doesn't matter from the libvpx point of view,
  280. # since a static library built for one works on the others.
  281. # The PlatformToolset field needs to be set in sync with this;
  282. # for Windows Store and Windows Phone Silverlight it should be
  283. # v120 while it should be v120_wp81 if the type is Windows Phone.
  284. tag_content ApplicationType "Windows Store"
  285. tag_content ApplicationTypeRevision 8.1
  286. fi
  287. close_tag PropertyGroup
  288. tag Import \
  289. Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
  290. for plat in "${platforms[@]}"; do
  291. for config in Release Debug; do
  292. open_tag PropertyGroup \
  293. Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \
  294. Label="Configuration"
  295. if [ "$proj_kind" = "exe" ]; then
  296. tag_content ConfigurationType Application
  297. elif [ "$proj_kind" = "dll" ]; then
  298. tag_content ConfigurationType DynamicLibrary
  299. else
  300. tag_content ConfigurationType StaticLibrary
  301. fi
  302. if [ "$vs_ver" = "11" ]; then
  303. if [ "$plat" = "ARM" ]; then
  304. # Setting the wp80 toolchain automatically sets the
  305. # WINAPI_FAMILY define, which is required for building
  306. # code for arm with the windows headers. Alternatively,
  307. # one could add AppContainerApplication=true in the Globals
  308. # section and add PrecompiledHeader=NotUsing and
  309. # CompileAsWinRT=false in ClCompile and SubSystem=Console
  310. # in Link.
  311. tag_content PlatformToolset v110_wp80
  312. else
  313. tag_content PlatformToolset v110
  314. fi
  315. fi
  316. if [ "$vs_ver" = "12" ]; then
  317. # Setting a PlatformToolset indicating windows phone isn't
  318. # enough to build code for arm with MSVC 2013, one strictly
  319. # has to enable AppContainerApplication as well.
  320. tag_content PlatformToolset v120
  321. fi
  322. if [ "$vs_ver" = "14" ]; then
  323. tag_content PlatformToolset v140
  324. fi
  325. if [ "$vs_ver" = "15" ]; then
  326. tag_content PlatformToolset v141
  327. fi
  328. tag_content CharacterSet Unicode
  329. if [ "$config" = "Release" ]; then
  330. tag_content WholeProgramOptimization true
  331. fi
  332. close_tag PropertyGroup
  333. done
  334. done
  335. tag Import \
  336. Project="\$(VCTargetsPath)\\Microsoft.Cpp.props"
  337. open_tag ImportGroup \
  338. Label="PropertySheets"
  339. tag Import \
  340. Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" \
  341. Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" \
  342. Label="LocalAppDataPlatform"
  343. close_tag ImportGroup
  344. tag PropertyGroup \
  345. Label="UserMacros"
  346. for plat in "${platforms[@]}"; do
  347. plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
  348. for config in Debug Release; do
  349. open_tag PropertyGroup \
  350. Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
  351. tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\"
  352. tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\"
  353. if [ "$proj_kind" == "lib" ]; then
  354. if [ "$config" == "Debug" ]; then
  355. config_suffix=d
  356. else
  357. config_suffix=""
  358. fi
  359. tag_content TargetName "${name}${lib_sfx}${config_suffix}"
  360. fi
  361. close_tag PropertyGroup
  362. done
  363. done
  364. for plat in "${platforms[@]}"; do
  365. for config in Debug Release; do
  366. open_tag ItemDefinitionGroup \
  367. Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
  368. if [ "$name" == "vpx" ]; then
  369. hostplat=$plat
  370. if [ "$hostplat" == "ARM" ]; then
  371. hostplat=Win32
  372. fi
  373. fi
  374. open_tag ClCompile
  375. if [ "$config" = "Debug" ]; then
  376. opt=Disabled
  377. runtime=$debug_runtime
  378. curlibs=$debug_libs
  379. debug=_DEBUG
  380. else
  381. opt=MaxSpeed
  382. runtime=$release_runtime
  383. curlibs=$libs
  384. tag_content FavorSizeOrSpeed Speed
  385. debug=NDEBUG
  386. fi
  387. extradefines=";$defines"
  388. tag_content Optimization $opt
  389. tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)"
  390. tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)"
  391. tag_content RuntimeLibrary $runtime
  392. tag_content WarningLevel Level3
  393. if ${werror:-false}; then
  394. tag_content TreatWarningAsError true
  395. fi
  396. if [ $vs_ver -ge 11 ]; then
  397. # We need to override the defaults for these settings
  398. # if AppContainerApplication is set.
  399. tag_content CompileAsWinRT false
  400. tag_content PrecompiledHeader NotUsing
  401. tag_content SDLCheck false
  402. fi
  403. close_tag ClCompile
  404. case "$proj_kind" in
  405. exe)
  406. open_tag Link
  407. tag_content GenerateDebugInformation true
  408. # Console is the default normally, but if
  409. # AppContainerApplication is set, we need to override it.
  410. tag_content SubSystem Console
  411. close_tag Link
  412. ;;
  413. dll)
  414. open_tag Link
  415. tag_content GenerateDebugInformation true
  416. tag_content ModuleDefinitionFile $module_def
  417. close_tag Link
  418. ;;
  419. lib)
  420. ;;
  421. esac
  422. close_tag ItemDefinitionGroup
  423. done
  424. done
  425. open_tag ItemGroup
  426. generate_filter "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s;S"
  427. close_tag ItemGroup
  428. open_tag ItemGroup
  429. generate_filter "Header Files" "h;hm;inl;inc;xsd"
  430. close_tag ItemGroup
  431. open_tag ItemGroup
  432. generate_filter "Build Files" "mk"
  433. close_tag ItemGroup
  434. open_tag ItemGroup
  435. generate_filter "References" "vcxproj"
  436. close_tag ItemGroup
  437. tag Import \
  438. Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets"
  439. open_tag ImportGroup \
  440. Label="ExtensionTargets"
  441. close_tag ImportGroup
  442. close_tag Project
  443. # This must be done from within the {} subshell
  444. echo "Ignored files list (${#file_list[@]} items) is:" >&2
  445. for f in "${file_list[@]}"; do
  446. echo " $f" >&2
  447. done
  448. }
  449. # This regexp doesn't catch most of the strings in the vcxproj format,
  450. # since they're like <tag>path</tag> instead of <tag attr="path" />
  451. # as previously. It still seems to work ok despite this.
  452. generate_vcxproj |
  453. sed -e '/"/s;\([^ "]\)/;\1\\;g' |
  454. sed -e '/xmlns/s;\\;/;g' > ${outfile}
  455. exit