blob: e98611d10249f525eceb573733888d4bb90ece25 [file] [log] [blame]
David Ghandehari8c5039b2016-08-17 19:39:30 -07001#!/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) 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" ]) && $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)
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|*.s) 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)
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} &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 ;;
271esac
272
273generate_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 tag_content CharacterSet Unicode
351 if [ "$config" = "Release" ]; then
352 tag_content WholeProgramOptimization true
353 fi
354 close_tag PropertyGroup
355 done
356 done
357
358 tag Import \
359 Project="\$(VCTargetsPath)\\Microsoft.Cpp.props"
360
361 open_tag ImportGroup \
362 Label="PropertySheets"
363 tag Import \
364 Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" \
365 Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" \
366 Label="LocalAppDataPlatform"
367 close_tag ImportGroup
368
369 tag PropertyGroup \
370 Label="UserMacros"
371
372 for plat in "${platforms[@]}"; do
373 plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
374 for config in Debug Release; do
375 open_tag PropertyGroup \
376 Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
377 tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\"
378 tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\"
379 if [ "$proj_kind" == "lib" ]; then
380 if [ "$config" == "Debug" ]; then
381 config_suffix=d
382 else
383 config_suffix=""
384 fi
385 tag_content TargetName "${name}${lib_sfx}${config_suffix}"
386 fi
387 close_tag PropertyGroup
388 done
389 done
390
391 for plat in "${platforms[@]}"; do
392 for config in Debug Release; do
393 open_tag ItemDefinitionGroup \
394 Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
395 if [ "$name" == "vpx" ]; then
396 hostplat=$plat
397 if [ "$hostplat" == "ARM" ]; then
398 hostplat=Win32
399 fi
400 fi
401 open_tag ClCompile
402 if [ "$config" = "Debug" ]; then
403 opt=Disabled
404 runtime=$debug_runtime
405 curlibs=$debug_libs
406 debug=_DEBUG
407 else
408 opt=MaxSpeed
409 runtime=$release_runtime
410 curlibs=$libs
411 tag_content FavorSizeOrSpeed Speed
412 debug=NDEBUG
413 fi
414 extradefines=";$defines"
415 tag_content Optimization $opt
416 tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)"
417 tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)"
418 tag_content RuntimeLibrary $runtime
419 tag_content WarningLevel Level3
420 if ${werror:-false}; then
421 tag_content TreatWarningAsError true
422 fi
423 if [ $vs_ver -ge 11 ]; then
424 # We need to override the defaults for these settings
425 # if AppContainerApplication is set.
426 tag_content CompileAsWinRT false
427 tag_content PrecompiledHeader NotUsing
428 tag_content SDLCheck false
429 fi
430 close_tag ClCompile
431 case "$proj_kind" in
432 exe)
433 open_tag Link
434 tag_content GenerateDebugInformation true
435 # Console is the default normally, but if
436 # AppContainerApplication is set, we need to override it.
437 tag_content SubSystem Console
438 close_tag Link
439 ;;
440 dll)
441 open_tag Link
442 tag_content GenerateDebugInformation true
443 tag_content ModuleDefinitionFile $module_def
444 close_tag Link
445 ;;
446 lib)
447 ;;
448 esac
449 close_tag ItemDefinitionGroup
450 done
451
452 done
453
454 open_tag ItemGroup
455 generate_filter "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s"
456 close_tag ItemGroup
457 open_tag ItemGroup
458 generate_filter "Header Files" "h;hm;inl;inc;xsd"
459 close_tag ItemGroup
460 open_tag ItemGroup
461 generate_filter "Build Files" "mk"
462 close_tag ItemGroup
463 open_tag ItemGroup
464 generate_filter "References" "vcxproj"
465 close_tag ItemGroup
466
467 tag Import \
468 Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets"
469
470 open_tag ImportGroup \
471 Label="ExtensionTargets"
472 close_tag ImportGroup
473
474 close_tag Project
475
476 # This must be done from within the {} subshell
477 echo "Ignored files list (${#file_list[@]} items) is:" >&2
478 for f in "${file_list[@]}"; do
479 echo " $f" >&2
480 done
481}
482
483# This regexp doesn't catch most of the strings in the vcxproj format,
484# since they're like <tag>path</tag> instead of <tag attr="path" />
485# as previously. It still seems to work ok despite this.
486generate_vcxproj |
487 sed -e '/"/s;\([^ "]\)/;\1\\;g' |
488 sed -e '/xmlns/s;\\;/;g' > ${outfile}
489
490exit