Imported Upstream version 1.64.0
[platform/upstream/boost.git] / tools / build / src / tools / msvc.jam
1 # Copyright (c) 2003 David Abrahams
2 # Copyright (c) 2005 Vladimir Prus
3 # Copyright (c) 2005 Alexey Pakhunov
4 # Copyright (c) 2006 Bojan Resnik
5 # Copyright (c) 2006 Ilya Sokolov
6 # Copyright (c) 2007-2017 Rene Rivera
7 # Copyright (c) 2008 Jurko Gospodnetic
8 # Copyright (c) 2014 Microsoft Corporation
9 #
10 # Distributed under the Boost Software License, Version 1.0.
11 # (See accompanying file LICENSE_1_0.txt or copy at
12 # http://www.boost.org/LICENSE_1_0.txt)
13
14 ################################################################################
15 #
16 # MSVC Boost Build toolset module.
17 # --------------------------------
18 #
19 # All toolset versions need to have their location either auto-detected or
20 # explicitly specified except for the special 'default' version that expects the
21 # environment to find the needed tools or report an error.
22 #
23 ################################################################################
24
25 import "class" : new ;
26 import common ;
27 import feature ;
28 import generators ;
29 import mc ;
30 import midl ;
31 import os ;
32 import path ;
33 import pch ;
34 import property ;
35 import rc ;
36 import set ;
37 import toolset ;
38 import type ;
39
40
41 type.register MANIFEST : manifest ;
42 feature.feature embed-manifest : on off : incidental propagated ;
43 feature.feature embed-manifest-file : : free dependency ;
44
45 type.register PDB : pdb ;
46
47
48 ################################################################################
49 #
50 # Public rules.
51 #
52 ################################################################################
53
54 # Initialize a specific toolset version configuration. As the result, path to
55 # compiler and, possible, program names are set up, and will be used when that
56 # version of compiler is requested. For example, you might have:
57 #
58 #    using msvc : 6.5 : cl.exe ;
59 #    using msvc : 7.0 : Y:/foo/bar/cl.exe ;
60 #
61 # The version parameter may be omitted:
62 #
63 #    using msvc : : Z:/foo/bar/cl.exe ;
64 #
65 # The following keywords have special meanings when specified as versions:
66 #   - all     - all detected but not yet used versions will be marked as used
67 #               with their default options.
68 #   - default - this is an equivalent to an empty version.
69 #
70 # Depending on a supplied version, detected configurations and presence 'cl.exe'
71 # in the path different results may be achieved. The following table describes
72 # the possible scenarios:
73 #
74 #                                      Nothing            "x.y"
75 # Passed   Nothing       "x.y"         detected,          detected,
76 # version  detected      detected      cl.exe in path     cl.exe in path
77 #
78 # default  Error         Use "x.y"     Create "default"   Use "x.y"
79 # all      None          Use all       None               Use all
80 # x.y      -             Use "x.y"     -                  Use "x.y"
81 # a.b      Error         Error         Create "a.b"       Create "a.b"
82 #
83 # "x.y" - refers to a detected version;
84 # "a.b" - refers to an undetected version.
85 #
86 # FIXME: Currently the command parameter and the <compiler> property parameter
87 # seem to overlap in duties. Remove this duplication. This seems to be related
88 # to why someone started preparing to replace init with configure rules.
89 #
90 rule init (
91     # The msvc version being configured. When omitted the tools invoked when no
92     # explicit version is given will be configured.
93     version ?
94
95     # The command used to invoke the compiler. If not specified:
96     #   - if version is given, default location for that version will be
97     #     searched
98     #
99     #   - if version is not given, default locations for MSVC 9.0, 8.0, 7.1, 7.0
100     #     and 6.* will be searched
101     #
102     #   - if compiler is not found in the default locations, PATH will be
103     #     searched.
104     : command *
105
106     # Options may include:
107     #
108     #     All options shared by multiple toolset types as handled by the
109     #   common.handle-options() rule, e.g. <cflags>, <compileflags>, <cxxflags>,
110     #   <fflags> & <linkflags>.
111     #
112     #   <assembler>
113     #   <compiler>
114     #   <idl-compiler>
115     #   <linker>
116     #   <mc-compiler>
117     #   <resource-compiler>
118     #       Exact tool names to be used by this msvc toolset configuration.
119     #
120     #   <compiler-filter>
121     #       Command through which to pipe the output of running the compiler.
122     #     For example to pass the output to STLfilt.
123     #
124     #   <setup>
125     #       Global setup command to invoke before running any of the msvc tools.
126     #     It will be passed additional option parameters depending on the actual
127     #     target platform.
128     #
129     #   <setup-amd64>
130     #   <setup-i386>
131     #   <setup-ia64>
132     #   <setup-arm>
133     #   <setup-phone-i386>
134     #   <setup-phone-arm>
135     #       Platform specific setup command to invoke before running any of the
136     #     msvc tools used when builing a target for a specific platform, e.g.
137     #     when building a 32 or 64 bit executable.
138     #
139     #   <rewrite-setup-scripts>
140     #       Whether to rewrite setup scripts. New scripts will be output in
141     #     TEMP directory and will be used instead of originals in build actions.
142     #     Possible values:
143     #       * on - rewrite scripts, if they do not already exist (default)
144     #       * always - always rewrite scripts, even if they already exist
145     #       * off - use original setup scripts
146     : options *
147 )
148 {
149     if $(command)
150     {
151         options += <command>$(command) ;
152     }
153     configure $(version) : $(options) ;
154 }
155
156
157 # 'configure' is a newer version of 'init'. The parameter 'command' is passed as
158 # a part of the 'options' list. See the 'init' rule comment for more detailed
159 # information.
160 #
161 rule configure ( version ? : options * )
162 {
163     switch $(version)
164     {
165         case "all" :
166             if $(options)
167             {
168                 import errors ;
169                 errors.error "MSVC toolset configuration: options should be"
170                     "empty when '$(version)' is specified." ;
171             }
172
173             # Configure (i.e. mark as used) all registered versions.
174             local all-versions = [ $(.versions).all ] ;
175             if ! $(all-versions)
176             {
177                 if $(.debug-configuration)
178                 {
179                     ECHO "notice: [msvc-cfg] Asked to configure all registered"
180                         "msvc toolset versions when there are none currently"
181                         "registered." ;
182                 }
183             }
184             else
185             {
186                 for local v in $(all-versions)
187                 {
188                     # Note that there is no need to skip already configured
189                     # versions here as this will request configure-really rule
190                     # to configure the version using default options which will
191                     # in turn cause it to simply do nothing in case the version
192                     # has already been configured.
193                     configure-really $(v) ;
194                 }
195             }
196
197         case "default" :
198             configure-really : $(options) ;
199
200         case * :
201             configure-really $(version) : $(options) ;
202     }
203 }
204
205
206 # Sets up flag definitions dependent on the compiler version used.
207 # - 'version' is the version of compiler in N.M format.
208 # - 'conditions' is the property set to be used as flag conditions.
209 # - 'toolset' is the toolset for which flag settings are to be defined.
210 #   This makes the rule reusable for other msvc-option-compatible compilers.
211 #
212 rule configure-version-specific ( toolset : version : conditions )
213 {
214     toolset.push-checking-for-flags-module unchecked ;
215     # Starting with versions 7.0, the msvc compiler have the /Zc:forScope and
216     # /Zc:wchar_t options that improve C++ standard conformance, but those
217     # options are off by default. If we are sure that the msvc version is at
218     # 7.*, add those options explicitly. We can be sure either if user specified
219     # version 7.* explicitly or if we auto-detected the version ourselves.
220     if ! [ MATCH ^(6\\.) : $(version) ]
221     {
222         toolset.flags $(toolset).compile CFLAGS $(conditions) : /Zc:forScope /Zc:wchar_t ;
223         toolset.flags $(toolset).compile.c++ C++FLAGS $(conditions) : /wd4675 ;
224
225         # Explicitly disable the 'function is deprecated' warning. Some msvc
226         # versions have a bug, causing them to emit the deprecation warning even
227         # with /W0.
228         toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>off : /wd4996 ;
229
230         if [ MATCH ^([78]\\.) : $(version) ]
231         {
232             # 64-bit compatibility warning deprecated since 9.0, see
233             # http://msdn.microsoft.com/en-us/library/yt4xw8fh.aspx
234             toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>all : /Wp64 ;
235         }
236     }
237
238     #
239     # Processor-specific optimization.
240     #
241
242     if [ MATCH ^([67]) : $(version) ]
243     {
244         # 8.0 deprecates some of the options.
245         toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed $(conditions)/<optimization>space : /Ogiy /Gs ;
246         toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed : /Ot ;
247         toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>space : /Os ;
248
249         toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set> : /GB ;
250         toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>i486 : /G4 ;
251         toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g5) : /G5 ;
252         toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g6) : /G6 ;
253         toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g7) : /G7 ;
254
255         # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math"
256         # tests will fail.
257         toolset.flags $(toolset).compile CFLAGS $(conditions) : /Op ;
258
259         # 7.1 and below have single-threaded static RTL.
260         toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>off/<runtime-link>static/<threading>single : /ML ;
261         toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>on/<runtime-link>static/<threading>single : /MLd ;
262     }
263     else
264     {
265         # 8.0 and above adds some more options.
266         toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set> : /favor:blend ;
267         toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set>$(.cpu-type-em64t) : /favor:EM64T ;
268         toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set>$(.cpu-type-amd64) : /favor:AMD64 ;
269
270         # 8.0 and above only has multi-threaded static RTL.
271         toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>off/<runtime-link>static/<threading>single : /MT ;
272         toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>on/<runtime-link>static/<threading>single : /MTd ;
273
274         # Specify target machine type so the linker will not need to guess.
275         toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-amd64) : /MACHINE:X64 ;
276         toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-i386)  : /MACHINE:X86 ;
277         toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-ia64)  : /MACHINE:IA64 ;
278         toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-arm)   : /MACHINE:ARM ;
279
280         # Make sure that manifest will be generated even if there is no
281         # dependencies to put there.
282         toolset.flags $(toolset).link LINKFLAGS $(conditions) : /MANIFEST ;
283     }
284
285     toolset.pop-checking-for-flags-module ;
286 }
287
288 # Feature for handling targeting different Windows API sets.
289 feature.feature windows-api : desktop store phone : propagated composite link-incompatible ;
290 feature.compose <windows-api>store : <define>WINAPI_FAMILY=WINAPI_FAMILY_APP <define>_WIN32_WINNT=0x0602 
291     <linkflags>/APPCONTAINER ;
292 feature.compose <windows-api>phone : <define>WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP <define>_WIN32_WINNT=0x0602 
293     <linkflags>/APPCONTAINER <linkflags>/NODEFAULTLIB:ole32.lib <linkflags>/NODEFAULTLIB:kernel32.lib <linkflags>WindowsPhoneCore.lib ;
294 feature.set-default windows-api : desktop ;
295
296
297 # Registers this toolset including all of its flags, features & generators. Does
298 # nothing on repeated calls.
299 #
300 rule register-toolset ( )
301 {
302     if ! msvc in [ feature.values toolset ]
303     {
304         register-toolset-really ;
305     }
306 }
307
308 rule resolve-possible-msvc-version-alias ( version )
309 {
310     if $(.version-alias-$(version))
311     {
312         version = $(.version-alias-$(version)) ;
313     }
314     return $(version) ;
315 }
316
317
318 # Declare action for creating static libraries. If library exists, remove it
319 # before adding files. See
320 # http://article.gmane.org/gmane.comp.lib.boost.build/4241 for rationale.
321 if [ os.name ] in NT
322 {
323     # The 'DEL' command would issue a message to stdout if the file does not
324     # exist, so need a check.
325     actions archive
326     {
327         if exist "$(<[1])" DEL "$(<[1])"
328         $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
329     }
330 }
331 else
332 {
333     actions archive
334     {
335         $(.RM) "$(<[1])"
336         $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
337     }
338 }
339
340
341 # For the assembler the following options are turned on by default:
342 #
343 #   -Zp4   align structures to 4 bytes
344 #   -Cp    preserve case of user identifiers
345 #   -Cx    preserve case in publics, externs
346 #
347 actions compile.asm
348 {
349     $(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)"
350 }
351
352
353 rule compile.c ( targets + : sources * : properties * )
354 {
355     C++FLAGS on $(targets[1]) = ;
356     get-rspline $(targets) : -TC ;
357     compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
358 }
359
360
361 rule compile.c.preprocess ( targets + : sources * : properties * )
362 {
363     C++FLAGS on $(targets[1]) = ;
364     get-rspline $(targets) : -TC ;
365     preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
366 }
367
368
369 rule compile.c.pch ( targets + : sources * : properties * )
370 {
371     C++FLAGS on $(targets[1]) = ;
372     get-rspline $(targets[1]) : -TC ;
373     get-rspline $(targets[2]) : -TC ;
374     local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
375     if $(pch-source)
376     {
377         DEPENDS $(<) : $(pch-source) ;
378         compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
379     }
380     else
381     {
382         compile-c-c++-pch $(targets) : $(sources) ;
383     }
384 }
385
386 toolset.flags msvc YLOPTION : "-Yl" ;
387
388 # Action for running the C/C++ compiler without using precompiled headers.
389 #
390 # WARNING: Synchronize any changes this in action with intel-win
391 #
392 # Notes regarding PDB generation, for when we use
393 # <debug-symbols>on/<debug-store>database:
394 #
395 # 1. PDB_CFLAG is only set for <debug-symbols>on/<debug-store>database, ensuring
396 #    that the /Fd flag is dropped if PDB_CFLAG is empty.
397 #
398 # 2. When compiling executables's source files, PDB_NAME is set on a per-source
399 #    file basis by rule compile-c-c++. The linker will pull these into the
400 #    executable's PDB.
401 #
402 # 3. When compiling library's source files, PDB_NAME is updated to <libname>.pdb
403 #    for each source file by rule archive, as in this case compiler must be used
404 #    to create a single PDB for our library.
405 #
406 actions compile-c-c++ bind PDB_NAME
407 {
408     $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER)
409 }
410
411 actions preprocess-c-c++ bind PDB_NAME
412 {
413     $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)"
414 }
415
416 rule compile-c-c++ ( targets + : sources * )
417 {
418     DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ;
419     DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
420     PDB_NAME on $(<) = $(<[1]:S=.pdb) ;
421     LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
422 }
423
424 rule preprocess-c-c++ ( targets + : sources * )
425 {
426     DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ;
427     DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
428     PDB_NAME on $(<) = $(<:S=.pdb) ;
429     LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
430 }
431
432 # Action for running the C/C++ compiler using precompiled headers. In addition
433 # to whatever else it needs to compile, this action also adds a temporary source
434 # .cpp file used to compile the precompiled headers themselves.
435 #
436 # The global .escaped-double-quote variable is used to avoid messing up Emacs
437 # syntax highlighting in the messy N-quoted code below.
438 actions compile-c-c++-pch
439 {
440     $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote)$(.nl))" $(.CC.FILTER)
441 }
442
443
444 # Action for running the C/C++ compiler using precompiled headers. An already
445 # built source file for compiling the precompiled headers is expected to be
446 # given as one of the source parameters.
447 actions compile-c-c++-pch-s
448 {
449     $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" $(.CC.FILTER)
450 }
451
452
453 rule compile.c++ ( targets + : sources * : properties * )
454 {
455     get-rspline $(targets) : -TP ;
456     compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
457 }
458
459 rule compile.c++.preprocess ( targets + : sources * : properties * )
460 {
461     get-rspline $(targets) : -TP ;
462     preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
463 }
464
465
466 rule compile.c++.pch ( targets + : sources * : properties * )
467 {
468     get-rspline $(targets[1]) : -TP ;
469     get-rspline $(targets[2]) : -TP ;
470     local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
471     if $(pch-source)
472     {
473         DEPENDS $(<) : $(pch-source) ;
474         compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
475     }
476     else
477     {
478         compile-c-c++-pch $(targets) : $(sources) ;
479     }
480 }
481
482
483 # See midl.jam for details.
484 #
485 actions compile.idl
486 {
487     $(.IDL) /nologo @"@($(<[1]:W).rsp:E=$(.nl)"$(>:W)" $(.nl)-D$(DEFINES) $(.nl)"-I$(INCLUDES:W)" $(.nl)-U$(UNDEFS) $(.nl)$(MIDLFLAGS) $(.nl)/tlb "$(<[1]:W)" $(.nl)/h "$(<[2]:W)" $(.nl)/iid "$(<[3]:W)" $(.nl)/proxy "$(<[4]:W)" $(.nl)/dlldata "$(<[5]:W)")"
488     $(.TOUCH_FILE) "$(<[4]:W)"
489     $(.TOUCH_FILE) "$(<[5]:W)"
490 }
491
492
493 actions compile.mc
494 {
495     $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"
496 }
497
498
499 actions compile.rc
500 {
501     $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)"
502 }
503
504
505 rule link ( targets + : sources * : properties * )
506 {
507     if <embed-manifest>on in $(properties)
508     {
509         if [ feature.get-values <embed-manifest-file> : $(properties) ]
510         {
511             DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ;
512             msvc.manifest.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ;
513         }
514         else 
515         {
516             msvc.manifest $(targets) : $(sources) : $(properties) ;
517         }
518     }
519 }
520
521 rule link.dll ( targets + : sources * : properties * )
522 {
523     DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
524     if <embed-manifest>on in $(properties)
525     {
526         if [ feature.get-values <embed-manifest-file> : $(properties) ]
527         {
528             DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ;
529             msvc.manifest.dll.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ;
530         }
531         else 
532         {
533             msvc.manifest.dll $(targets) : $(sources) : $(properties) ;
534         }
535     }
536 }
537
538 # Incremental linking a DLL causes no end of problems: if the actual exports do
539 # not change, the import .lib file is never updated. Therefore, the .lib is
540 # always out-of-date and gets rebuilt every time. I am not sure that incremental
541 # linking is such a great idea in general, but in this case I am sure we do not
542 # want it.
543
544 # Windows manifest is a new way to specify dependencies on managed DotNet
545 # assemblies and Windows native DLLs. The manifests are embedded as resources
546 # and are useful in any PE target (both DLL and EXE).
547
548 if [ os.name ] in NT
549 {
550     actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
551     {
552         $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
553         if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%
554     }
555
556     actions manifest
557     {
558         if exist "$(<[1]).manifest" (
559             $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
560         )
561     }
562
563     actions manifest.user bind EMBED_MANIFEST_FILE
564     {
565         $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);1"
566     }
567
568     actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
569     {
570         $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
571         if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%
572     }
573
574     actions manifest.dll
575     {
576         if exist "$(<[1]).manifest" (
577             $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
578         )
579     }
580     actions manifest.dll.user bind EMBED_MANIFEST_FILE
581     {
582         $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2"
583     }
584 }
585 else
586 {
587     actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
588     {
589         $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
590     }
591
592     actions manifest
593     {
594         if test -e "$(<[1]).manifest"; then
595             $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);1"
596         fi
597     }
598
599     actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
600     {
601         $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
602     }
603
604     actions manifest.dll
605     {
606         if test -e "$(<[1]).manifest"; then
607             $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2"
608         fi
609     }
610
611     actions manifest.dll.user bind EMBED_MANIFEST_FILE
612     {
613         $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2"
614     }
615 }
616
617 # This rule sets up the pdb file that will be used when generating static
618 # libraries and the debug-store option is database, so that the compiler puts
619 # all the debug info into a single .pdb file named after the library.
620 #
621 # Poking at source targets this way is probably not clean, but it is the
622 # easiest approach.
623 #
624 rule archive ( targets + : sources * : properties * )
625 {
626     PDB_NAME on $(>) = $(<[1]:S=.pdb) ;
627     LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
628 }
629
630
631 ################################################################################
632 #
633 # Classes.
634 #
635 ################################################################################
636
637 class msvc-pch-generator : pch-generator
638 {
639     import property-set ;
640
641     rule run-pch ( project name ? : property-set : sources * )
642     {
643         # Searching for the header and source file in the sources.
644         local pch-header ;
645         local pch-source ;
646         for local s in $(sources)
647         {
648             if [ type.is-derived [ $(s).type ] H ]
649             {
650                 pch-header = $(s) ;
651             }
652             else if
653                 [ type.is-derived [ $(s).type ] CPP ] ||
654                 [ type.is-derived [ $(s).type ] C ]
655             {
656                 pch-source = $(s) ;
657             }
658         }
659
660         if ! $(pch-header)
661         {
662             import errors : user-error : errors.user-error ;
663             errors.user-error "can not build pch without pch-header" ;
664         }
665
666         # If we do not have the PCH source - that is fine. We will just create a
667         # temporary .cpp file in the action.
668
669         local generated = [ generator.run $(project) $(name)
670             : [ property-set.create
671                 # Passing of <pch-source> is a dirty trick, needed because
672                 # non-composing generators with multiple inputs are subtly
673                 # broken. For more detailed information see:
674                 # https://zigzag.cs.msu.su:7813/boost.build/ticket/111
675                 <pch-source>$(pch-source)
676                 [ $(property-set).raw ] ]
677             : $(pch-header) ] ;
678
679         local pch-file ;
680         for local g in $(generated)
681         {
682             if [ type.is-derived [ $(g).type ] PCH ]
683             {
684                 pch-file = $(g) ;
685             }
686         }
687
688         return [ property-set.create <pch-header>$(pch-header)
689             <pch-file>$(pch-file) ] $(generated) ;
690     }
691 }
692
693
694 ################################################################################
695 #
696 # Local rules.
697 #
698 ################################################################################
699
700 # Detects versions listed as '.known-versions' by checking registry information,
701 # environment variables & default paths. Supports both native Windows and
702 # Cygwin.
703 #
704 local rule auto-detect-toolset-versions ( )
705 {
706     if [ os.name ] in NT CYGWIN
707     {
708         # Get installation paths from the registry.
709         for local i in $(.known-versions)
710         {
711             if $(.version-$(i)-reg)
712             {
713                 local vc-path ;
714                 for local x in "" "Wow6432Node\\"
715                 {
716                     vc-path += [ W32_GETREG
717                         "HKEY_LOCAL_MACHINE\\SOFTWARE\\"$(x)"\\Microsoft\\"$(.version-$(i)-reg)
718                         : "ProductDir" ] ;
719                 }
720
721                 if $(vc-path)
722                 {
723                     vc-path = [ path.join [ path.make-NT $(vc-path[1]) ] "bin" ] ;
724                     register-configuration $(i) : [ path.native $(vc-path[1]) ] ;
725                 }
726             }
727         }
728     }
729
730     # Check environment and default installation paths.
731     for local i in $(.known-versions)
732     {
733         if ! $(i) in [ $(.versions).all ]
734         {
735             register-configuration $(i) : [ default-path $(i) ] ;
736         }
737     }
738 }
739
740 # Helper rule to generate a faster alternative to MSVC setup scripts.
741 # We used to call MSVC setup scripts directly in every action, however in
742 # newer MSVC versions (10.0+) they make long-lasting registry queries 
743 # which have a significant impact on build time.
744 rule maybe-rewrite-setup ( toolset : setup-script : setup-options : version : rewrite-setup ? )
745 {
746     local result = $(setup-script)" "$(setup-options) ;
747     # At the moment we only know how to rewrite scripts with cmd shell.
748     if ( [ os.name ] in NT ) && ( $(rewrite-setup) != off )
749     {
750         setup-script-id = b2_$(toolset)_$(version)_$(setup-script:B) ;
751         if $(setup-options)-is-not-empty
752         {
753             setup-script-id = $(setup-script-id)_$(setup-options) ;
754         }
755
756         if $(.$(setup-script-id))
757         {
758             errors.error rewriting setup script for the second time ;
759         }
760
761         local tmpdir = [ os.environ TEMP ] ;
762         local replacement = [ path.native $(tmpdir)/$(setup-script-id).cmd ] ;
763         if ( $(rewrite-setup) = always ) || ( ! [ path.exists $(replacement) ] )
764         {
765             local original-vars = [ SPLIT_BY_CHARACTERS [ SHELL set ] : "\n" ] ;
766             local new-vars = [ SPLIT_BY_CHARACTERS [ SHELL "$(setup-script) $(setup-options)>nul && set" ] : "\n" ] ;
767             local diff-vars = [ set.difference $(new-vars) : $(original-vars) ] ;
768             if $(diff-vars)
769             {
770                 local target = <new-setup-script>$(replacement) ;
771                 FILE_CONTENTS on $(target) = "SET "$(diff-vars) ;
772                 ALWAYS $(target) ;
773                 msvc.write-setup-script $(target) ;
774                 UPDATE_NOW $(target) : : ignore-minus-n ;
775                 .$(setup-script-id) = $(replacement) ;
776                 result = "\""$(replacement)"\"" ;
777             }
778         }
779         else
780         {
781             result = "\""$(replacement)"\"" ;
782         }
783     }
784     return $(result) ;
785 }
786
787 actions write-setup-script
788 {
789     @($(STDOUT):E=$(FILE_CONTENTS:J=$(.nl))) > "$(<)"
790 }
791
792
793 # Local helper rule to create the vcvars setup command for given architecture
794 # and options.
795 #
796 local rule generate-setup-cmd ( version : command : parent : options * : cpu : global-setup ? : default-global-setup-options : default-setup )
797 {
798     local setup-prefix = "call " ;
799     local setup-suffix = " >nul"$(.nl) ;
800     if ! [ os.name ] in NT
801     {
802         setup-prefix = "cmd.exe /S /C call " ;
803         setup-suffix = " \">nul\" \"&&\" " ;
804     }
805
806     local setup-options ;
807     local setup = [ feature.get-values <setup-$(cpu)> : $(options) ] ;
808     
809     if ! $(setup)-is-defined
810     {
811         if $(global-setup)-is-defined
812         {
813             setup = $(global-setup) ;
814                         
815             # If needed we can easily add using configuration flags
816             # here for overriding which options get passed to the
817             # global setup command for which target platform:
818             # setup-options = [ feature.get-values <setup-options-$(c)> : $(options) ] ;
819             setup-options ?= $(default-global-setup-options) ;
820         }
821         else
822         {
823             if [ MATCH "(14.1)" : $(version) ]
824             {
825                 if $(.debug-configuration)
826                 {
827                     ECHO 'notice: [generate-setup-cmd] $(version) is 14.1' ;
828                 }
829                 parent = [ path.native [ path.join  $(parent) "..\\..\\..\\..\\..\\Auxiliary\\Build" ] ] ;
830             }
831             setup = [ locate-default-setup $(command) : $(parent) : $(default-setup) ] ;
832             setup ?= [ path.join  $(parent) "vcvarsall.bat" ] ;
833         }
834     }
835     
836     # Cygwin to Windows path translation.
837     setup = "\""$(setup:W)"\"" ;
838
839     # Append setup options to the setup name and add the final setup
840     # prefix & suffix.
841     setup-options ?= "" ;
842     local rewrite = [ feature.get-values <rewrite-setup-scripts> : $(options) ] ;
843     setup = [ maybe-rewrite-setup msvc : $(setup:J=" ") : $(setup-options:J=" ") : $(version) : $(rewrite) ] ;
844     setup = $(setup-prefix)$(setup)$(setup-suffix) ;
845     
846     return $(setup) ;
847 }
848
849
850 # Worker rule for toolset version configuration. Takes an explicit version id or
851 # nothing in case it should configure the default toolset version (the first
852 # registered one or a new 'default' one in case no toolset versions have been
853 # registered yet).
854 #
855 local rule configure-really ( version ? : options * )
856 {
857     local v = $(version) ;
858
859     # Decide what the 'default' version is.
860     if ! $(v)
861     {
862         # Take the best registered (i.e. auto-detected) version.
863         version = [ $(.versions).all ] ;
864         for local known in $(.known-versions)
865         {
866             if $(known) in $(version)
867             {
868                 version = $(known) ;
869                 break ;
870             }
871         }
872         version = $(version[1]) ;
873         v = $(version) ;
874
875         # Note: 'version' can still be empty at this point if no versions have
876         # been auto-detected.
877         version ?= "default" ;
878     }
879
880     # Version alias -> real version number.
881     version = [ resolve-possible-msvc-version-alias $(version) ] ;
882
883     # Check whether the selected configuration is already in use.
884     if $(version) in [ $(.versions).used ]
885     {
886         # Allow multiple 'toolset.using' calls for the same configuration if the
887         # identical sets of options are used.
888         if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] )
889         {
890             import errors ;
891             errors.error "MSVC toolset configuration: Toolset version"
892                 "'$(version)' already configured." ;
893         }
894     }
895     else
896     {
897         # Register a new configuration.
898         $(.versions).register $(version) ;
899
900         # Add user-supplied to auto-detected options.
901         options = [ $(.versions).get $(version) : options ] $(options) ;
902
903         # Mark the configuration as 'used'.
904         $(.versions).use $(version) ;
905
906         # Generate conditions and save them.
907         local conditions = [ common.check-init-parameters msvc : version $(v) ]
908             ;
909
910         $(.versions).set $(version) : conditions : $(conditions) ;
911
912         local command = [ feature.get-values <command> : $(options) ] ;
913
914         # For 14.1 we need the exact version as MS is planning rolling updates
915         # that will cause our `setup-cmd` to become invalid
916         exact-version = [ MATCH "(14\.10\.[0-9\.]+)" : $(command) ] ;
917
918         # If version is specified, we try to search first in default paths, and
919         # only then in PATH.
920         command = [ common.get-invocation-command msvc : cl.exe : $(command) :
921             [ default-paths $(version) ] : $(version) ] ;
922
923         if ( ! $(version) || $(version) = "default" ) && ! $(command:D)
924         {
925             ECHO ;
926             ECHO warning:
927                 "Did not find command for MSVC toolset."
928                 "If you have Visual Studio 2017 installed you will need to"
929                 "specify the full path to the command,"
930                 "set VS150COMNTOOLS for your installation,"
931                 "or"
932                 "build from the 'Visual Studio Command Prompt for VS 2017'."
933                 ;
934             ECHO ;
935         }
936
937         common.handle-options msvc : $(conditions) : $(command) : $(options) ;
938
939         if ! $(version)
940         {
941             # Even if version is not explicitly specified, try to detect the
942             # version from the path.
943             # FIXME: We currently detect both Microsoft Visual Studio 9.0 and
944             # 9.0express as 9.0 here.
945             if [ MATCH "(MSVC\\14.1)" : $(command) ]
946             {
947                 version = 14.1 ;
948             }
949             else if [ MATCH "(Microsoft Visual Studio 14)" : $(command) ]
950             {
951                 version = 14.0 ;
952             }
953             else if [ MATCH "(Microsoft Visual Studio 12)" : $(command) ]
954             {
955                 version = 12.0 ;
956             }
957             else if [ MATCH "(Microsoft Visual Studio 11)" : $(command) ]
958             {
959                 version = 11.0 ;
960             }
961             else if [ MATCH "(Microsoft Visual Studio 10)" : $(command) ]
962             {
963                 version = 10.0 ;
964             }
965             else if [ MATCH "(Microsoft Visual Studio 9)" : $(command) ]
966             {
967                 version = 9.0 ;
968             }
969             else if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ]
970             {
971                 version = 8.0 ;
972             }
973             else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ]
974             {
975                 version = 7.1 ;
976             }
977             else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" :
978                 $(command) ]
979             {
980                 version = 7.1toolkit ;
981             }
982             else if [ MATCH "(.NET[\/\\]VC7)" : $(command) ]
983             {
984                 version = 7.0 ;
985             }
986             else
987             {
988                 version = 6.0 ;
989             }
990         }
991
992         # Generate and register setup command.
993
994         local below-8.0 = [ MATCH ^([67]\\.) : $(version) ] ;
995         local below-11.0 = [ MATCH ^([6789]\\.|10\\.) : $(version) ] ;
996         
997         local cpu = i386 amd64 ia64 arm ;
998         if $(below-8.0)
999         {
1000             cpu = i386 ;
1001         }
1002         else if $(below-11.0)
1003         {
1004             cpu = i386 amd64 ia64 ;
1005         }
1006         
1007         local setup-amd64 ;
1008         local setup-i386 ;
1009         local setup-ia64 ;
1010         local setup-arm ;
1011         local setup-phone-i386 ;
1012         local setup-phone-arm ;
1013
1014         if $(command)
1015         {
1016             # TODO: Note that if we specify a non-existant toolset version then
1017             # this rule may find and use a corresponding compiler executable
1018             # belonging to an incorrect toolset version. For example, if you
1019             # have only MSVC 7.1 installed, have its executable on the path and
1020             # specify you want Boost Build to use MSVC 9.0, then you want Boost
1021             # Build to report an error but this may cause it to silently use the
1022             # MSVC 7.1 compiler even though it thinks it is using the msvc-9.0
1023             # toolset version.
1024             command = [ common.get-absolute-tool-path $(command[-1]) ] ;
1025         }
1026
1027         if $(command)
1028         {
1029             local parent = [ path.make $(command) ] ;
1030             parent = [ path.parent $(parent) ] ;
1031             parent = [ path.native $(parent) ] ;
1032
1033             # Setup will be used if the command name has been specified. If
1034             # setup is not specified explicitly then a default setup script will
1035             # be used instead. Setup scripts may be global or architecture/
1036             # /platform/cpu specific. Setup options are used only in case of
1037             # global setup scripts.
1038
1039             # Default setup scripts provided with different VC distributions:
1040             #
1041             #   VC 7.1 had only the vcvars32.bat script specific to 32 bit i386
1042             # builds. It was located in the bin folder for the regular version
1043             # and in the root folder for the free VC 7.1 tools.
1044             #
1045             #   Later 8.0 & 9.0 versions introduce separate platform specific
1046             # vcvars*.bat scripts (e.g. 32 bit, 64 bit AMD or 64 bit Itanium)
1047             # located in or under the bin folder. Most also include a global
1048             # vcvarsall.bat helper script located in the root folder which runs
1049             # one of the aforementioned vcvars*.bat scripts based on the options
1050             # passed to it. So far only the version coming with some PlatformSDK
1051             # distributions does not include this top level script but to
1052             # support those we need to fall back to using the worker scripts
1053             # directly in case the top level script can not be found.
1054
1055             local global-setup = [ feature.get-values <setup> : $(options) ] ;
1056             global-setup = $(global-setup[1]) ;
1057             local global-setup-phone = $(global-setup) ;
1058             if ! $(below-8.0)
1059             {
1060                 global-setup ?= [ locate-default-setup $(command) : $(parent) :
1061                     vcvarsall.bat ] ;
1062             }
1063
1064             local default-setup-amd64 = vcvarsx86_amd64.bat ;
1065             local default-setup-i386  = vcvars32.bat ;
1066             local default-setup-ia64  = vcvarsx86_ia64.bat ;
1067             local default-setup-arm   = vcvarsx86_arm.bat ;
1068             local default-setup-phone-i386 = vcvarsphonex86.bat ;
1069             local default-setup-phone-arm = vcvarsphonex86_arm.bat ;
1070
1071             # http://msdn2.microsoft.com/en-us/library/x4d2c09s(VS.80).aspx and
1072             # http://msdn2.microsoft.com/en-us/library/x4d2c09s(vs.90).aspx
1073             # mention an x86_IPF option, that seems to be a documentation bug
1074             # and x86_ia64 is the correct option.
1075             local default-global-setup-options-amd64 = x86_amd64 ;
1076             local default-global-setup-options-i386  = x86 ;
1077             local default-global-setup-options-ia64  = x86_ia64 ;
1078             local default-global-setup-options-arm   = x86_arm ;
1079
1080             # When using 64-bit Windows, and targeting 64-bit, it is possible to
1081             # use a native 64-bit compiler, selected by the "amd64" & "ia64"
1082             # parameters to vcvarsall.bat. There are two variables we can use --
1083             # PROCESSOR_ARCHITECTURE and PROCESSOR_IDENTIFIER. The first is
1084             # 'x86' when running 32-bit Windows, no matter which processor is
1085             # used, and 'AMD64' on 64-bit windows on x86 (either AMD64 or EM64T)
1086             # Windows.
1087             #
1088             if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITECTURE ] ]
1089             {
1090                 default-global-setup-options-amd64 = amd64 ;
1091             }
1092             # When Boost.Build itself is running as a 32-bit process on 64-bit
1093             # Windows, the above test will fail (since WOW64 simulates a 32-bit
1094             # environment, including environment values).  So check the WOW64
1095             # variable PROCESSOR_ARCHITEW6432 as well.
1096             if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITEW6432 ] ]
1097             {
1098                 default-global-setup-options-amd64 = amd64 ;
1099             }
1100             # TODO: The same 'native compiler usage' should be implemented for
1101             # the Itanium platform by using the "ia64" parameter. For this
1102             # though we need someone with access to this platform who can find
1103             # out how to correctly detect this case.
1104             else if $(somehow-detect-the-itanium-platform)
1105             {
1106                 default-global-setup-options-ia64 = ia64 ;
1107             }
1108
1109             for local c in $(cpu)
1110             {
1111                 exact-version ?= $(version) ;
1112                 setup-$(c) = [ generate-setup-cmd $(exact-version) : $(command) : $(parent) : $(options) : $(c) : $(global-setup) : $(default-global-setup-options-$(c)) : $(default-setup-$(c)) ] ;
1113             }
1114             
1115             # Windows phone has different setup scripts, located in a different directory hierarchy.
1116             # The 11.0 toolset can target Windows Phone 8.0 and the 12.0 toolset can target Windows Phone 8.1,
1117             # each of which have a different directory for their vcvars setup scripts.
1118             local phone-parent = [ path.native [ path.join $(parent) WPSDK ] ] ;
1119             local phone-directory = $(phone-parent) ;
1120             if [ MATCH "(11.0)" : $(version) ]
1121             {
1122                 phone-directory = [ path.native [ path.join $(phone-directory) WP80 ] ] ;
1123             }
1124             else if [ MATCH "(12.0)" : $(version) ]
1125             {
1126                 phone-directory = [ path.native [ path.join $(phone-directory) WP81 ] ] ;
1127             }
1128             global-setup-phone ?= [ locate-default-setup $(phone-directory) : $(phone-parent) : vcvarsphoneall.bat ] ;
1129                 
1130             # If can't locate default phone setup script then this VS version doesn't support Windows Phone.
1131             if $(global-setup-phone)-is-defined
1132             {
1133                 # i386 CPU is for the Windows Phone emulator in Visual Studio.
1134                 local phone-cpu = i386 arm ;
1135                 for local c in $(phone-cpu)
1136                 {
1137                     setup-phone-$(c) = [ generate-setup-cmd $(version) : $(phone-directory) : $(phone-parent) : $(options) : $(c) : $(global-setup-phone) : $(default-global-setup-options-$(c)) : $(default-setup-phone-$(c)) ] ;
1138                 }
1139             }
1140         }
1141
1142         # Get tool names (if any) and finish setup.
1143
1144         compiler = [ feature.get-values <compiler> : $(options) ] ;
1145         compiler ?= cl ;
1146
1147         linker = [ feature.get-values <linker> : $(options) ] ;
1148         linker ?= link ;
1149
1150         resource-compiler = [ feature.get-values <resource-compiler> : $(options) ] ;
1151         resource-compiler ?= rc ;
1152
1153         # Turn on some options for i386 assembler
1154         #  -coff  generate COFF format object file (compatible with cl.exe output)
1155         local default-assembler-amd64 = ml64 ;
1156         local default-assembler-i386  = "ml -coff" ;
1157         local default-assembler-ia64  = ias ;
1158         local default-assembler-ia64  = armasm ;
1159
1160         assembler = [ feature.get-values <assembler> : $(options) ] ;
1161
1162         idl-compiler = [ feature.get-values <idl-compiler> : $(options) ] ;
1163         idl-compiler ?= midl ;
1164
1165         mc-compiler = [ feature.get-values <mc-compiler> : $(options) ] ;
1166         mc-compiler ?= mc ;
1167
1168         manifest-tool = [ feature.get-values <manifest-tool> : $(options) ] ;
1169         manifest-tool ?= mt ;
1170
1171         local cc-filter = [ feature.get-values <compiler-filter> : $(options) ]
1172             ;
1173
1174         for local c in $(cpu)
1175         {
1176             # Setup script is not required in some configurations.
1177             setup-$(c) ?= "" ;
1178
1179             local cpu-conditions = $(conditions)/$(.cpu-arch-$(c)) ;
1180
1181             if $(.debug-configuration)
1182             {
1183                 for local cpu-condition in $(cpu-conditions)
1184                 {
1185                     ECHO "notice: [msvc-cfg] condition: '$(cpu-condition)', setup: '$(setup-$(c))'" ;
1186                 }
1187             }
1188
1189             local cpu-assembler = $(assembler) ;
1190             cpu-assembler ?= $(default-assembler-$(c)) ;
1191
1192             toolset.flags msvc.compile .RC  <windows-api>$(api)/$(cpu-conditions) : $(setup-$(c))$(resource-compiler) ;
1193             toolset.flags msvc.compile .IDL <windows-api>$(api)/$(cpu-conditions) : $(setup-$(c))$(idl-compiler) ;
1194             toolset.flags msvc.compile .MC  <windows-api>$(api)/$(cpu-conditions) : $(setup-$(c))$(mc-compiler) ;
1195             toolset.flags msvc.link    .MT  <windows-api>$(api)/$(cpu-conditions) : $(setup-$(c))$(manifest-tool) -nologo ;
1196
1197             for api in desktop store phone
1198             {
1199                 local setup-script = $(setup-$(c)) ;
1200                 if $(api) = phone
1201                 {
1202                     setup-script = $(setup-phone-$(c)) ;
1203                 }
1204                 if $(api) = desktop
1205                 {
1206                     toolset.flags msvc.compile .CC  <windows-api>$(api)/$(cpu-conditions) : $(setup-script)$(compiler) /Zm800 -nologo ;
1207                 }
1208                 else
1209                 {
1210                     toolset.flags msvc.compile .CC  <windows-api>$(api)/$(cpu-conditions) : $(setup-script)$(compiler) /Zm800 /ZW /EHsc -nologo ;
1211                 }
1212                 toolset.flags msvc.compile .ASM <windows-api>$(api)/$(cpu-conditions) : $(setup-script)$(cpu-assembler) -nologo ;
1213                 toolset.flags msvc.link    .LD  <windows-api>$(api)/$(cpu-conditions) : $(setup-script)$(linker) /NOLOGO /INCREMENTAL:NO ;
1214                 toolset.flags msvc.archive .LD  <windows-api>$(api)/$(cpu-conditions) : $(setup-script)$(linker) /lib /NOLOGO  ;
1215             }
1216
1217             if $(cc-filter)
1218             {
1219                 toolset.flags msvc .CC.FILTER $(cpu-conditions) : "|" $(cc-filter) ;
1220             }
1221         }
1222
1223         # Starting with Visual Studio 2013 the CRT is split into a desktop and app dll.
1224         # If targeting WinRT and 12.0 set lib path to link against app CRT.
1225         if [ MATCH "(12)" : $(version) ]
1226         {
1227             local storeLibPath = [ path.join $(parent) "lib/store" ] ;
1228             toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-i386) : [ path.native $(storeLibPath) ] ;
1229             toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-amd64) : [ path.native [ path.join $(storeLibPath) "amd64" ] ] ;
1230             toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-arm) : [ path.native [ path.join $(storeLibPath) "arm" ] ] ;
1231         }
1232
1233         # Set version-specific flags.
1234         configure-version-specific msvc : $(version) : $(conditions) ;
1235     }
1236 }
1237
1238
1239 # Returns the default installation path for the given version.
1240 #
1241 local rule default-path ( version )
1242 {
1243     # Use auto-detected path if possible.
1244     local result = [ feature.get-values <command> : [ $(.versions).get $(version)
1245         : options ] ] ;
1246
1247     if $(result)
1248     {
1249         result = $(result:D) ;
1250     }
1251     else
1252     {
1253         # Check environment.
1254         for local env in $(.version-$(version)-env)
1255         {
1256             local env-path = [ os.environ $(env) ] ;
1257             if $(env-path) && $(.version-$(version)-path)
1258             {
1259                 for local bin-path in $(.version-$(version)-path)
1260                 {
1261                     result = [ path.glob [ path.make $(env-path) ] : $(bin-path) ] ;
1262                     if $(result)
1263                     {
1264                         result = [ path.native $(result[1]) ] ;
1265                         break ;
1266                     }
1267                 }
1268             }
1269             if $(result)
1270             {
1271                 break ;
1272             }
1273         }
1274     }
1275
1276     return $(result) ;
1277 }
1278
1279
1280 # Returns either the default installation path (if 'version' is not empty) or
1281 # list of all known default paths (if no version is given)
1282 #
1283 local rule default-paths ( version ? )
1284 {
1285     local possible-paths ;
1286
1287     if $(version)
1288     {
1289         possible-paths += [ default-path $(version) ] ;
1290     }
1291     else
1292     {
1293         for local i in $(.known-versions)
1294         {
1295             possible-paths += [ default-path $(i) ] ;
1296         }
1297     }
1298
1299     return $(possible-paths) ;
1300 }
1301
1302
1303 rule get-rspline ( target : lang-opt )
1304 {
1305     CC_RSPLINE on $(target) = [ on $(target) return $(lang-opt) -U$(UNDEFS)
1306         $(CFLAGS) $(C++FLAGS) $(OPTIONS) -c $(.nl)-D$(DEFINES)
1307         $(.nl)\"-I$(INCLUDES:W)\" ] ;
1308 }
1309
1310 class msvc-linking-generator : linking-generator
1311 {
1312     # Calls the base version.  If necessary, also create a target for the
1313     # manifest file.specifying source's name as the name of the created
1314     # target. As result, the PCH will be named whatever.hpp.gch, and not
1315     # whatever.gch.
1316     rule generated-targets ( sources + : property-set : project name ? )
1317     {
1318         local result = [ linking-generator.generated-targets $(sources)
1319           : $(property-set) : $(project) $(name) ] ;
1320
1321         if $(result)
1322         {
1323             local name-main = [ $(result[0]).name ] ;
1324             local action = [ $(result[0]).action ] ;
1325
1326             if [ $(property-set).get <debug-symbols> ] = "on"
1327             {
1328                 # We force the exact name on PDB. The reason is tagging -- the
1329                 # tag rule may reasonably special case some target types, like
1330                 # SHARED_LIB. The tag rule will not catch PDBs, and it cannot
1331                 # even easily figure out if a PDB is paired with a SHARED_LIB,
1332                 # EXE or something else. Because PDBs always get the same name
1333                 # as the main target, with .pdb as extension, just force it.
1334                 local target = [ class.new file-target $(name-main:S=.pdb) exact
1335                     : PDB : $(project) : $(action) ] ;
1336                 local registered-target = [ virtual-target.register $(target) ]
1337                     ;
1338                 if $(target) != $(registered-target)
1339                 {
1340                     $(action).replace-targets $(target) : $(registered-target) ;
1341                 }
1342                 result += $(registered-target) ;
1343             }
1344
1345             if [ $(property-set).get <embed-manifest> ] = "off"
1346             {
1347                 # Manifest is an evil target. It has .manifest appened to the
1348                 # name of the main target, including extension, e.g.
1349                 # a.exe.manifest. We use the 'exact' name to achieve this
1350                 # effect.
1351                 local target = [ class.new file-target $(name-main).manifest
1352                     exact : MANIFEST : $(project) : $(action) ] ;
1353                 local registered-target = [ virtual-target.register $(target) ]
1354                     ;
1355                 if $(target) != $(registered-target)
1356                 {
1357                     $(action).replace-targets $(target) : $(registered-target) ;
1358                 }
1359                 result += $(registered-target) ;
1360             }
1361         }
1362         return $(result) ;
1363     }
1364 }
1365
1366
1367 # Unsafe worker rule for the register-toolset() rule. Must not be called
1368 # multiple times.
1369 #
1370 local rule register-toolset-really ( )
1371 {
1372     feature.extend toolset : msvc ;
1373
1374     # Intel and msvc supposedly have link-compatible objects.
1375     feature.subfeature toolset msvc : vendor : intel : propagated optional ;
1376
1377     # Inherit MIDL flags.
1378     toolset.inherit-flags msvc : midl ;
1379
1380     # Inherit MC flags.
1381     toolset.inherit-flags msvc : mc ;
1382
1383     # Dynamic runtime comes only in MT flavour.
1384     toolset.add-requirements
1385         <toolset>msvc,<runtime-link>shared:<threading>multi ;
1386
1387     # Declare msvc toolset specific features.
1388     {
1389         feature.feature debug-store : object database : propagated ;
1390         feature.feature pch-source  :                 : dependency free ;
1391     }
1392
1393     # Declare generators.
1394     {
1395         # TODO: Is it possible to combine these? Make the generators
1396         # non-composing so that they do not convert each source into a separate
1397         # .rsp file.
1398         generators.register [ new msvc-linking-generator msvc.link :
1399             OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : <toolset>msvc ] ;
1400         generators.register [ new msvc-linking-generator msvc.link.dll :
1401             OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB :
1402             <toolset>msvc <suppress-import-lib>false ] ;
1403         generators.register [ new msvc-linking-generator msvc.link.dll :
1404             OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB :
1405             <toolset>msvc <suppress-import-lib>true ] ;
1406
1407         generators.register-archiver msvc.archive : OBJ : STATIC_LIB : <toolset>msvc ;
1408         generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : <toolset>msvc ;
1409         generators.register-c-compiler msvc.compile.c : C : OBJ : <toolset>msvc ;
1410         generators.register-c-compiler msvc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : <toolset>msvc ;
1411         generators.register-c-compiler msvc.compile.c.preprocess : C : PREPROCESSED_C : <toolset>msvc ;
1412
1413         # Using 'register-c-compiler' adds the build directory to INCLUDES.
1414         generators.register-c-compiler msvc.compile.rc : RC : OBJ(%_res) : <toolset>msvc ;
1415         generators.override msvc.compile.rc : rc.compile.resource ;
1416         generators.register-standard msvc.compile.asm : ASM : OBJ : <toolset>msvc ;
1417
1418         generators.register-c-compiler msvc.compile.idl : IDL : MSTYPELIB H C(%_i) C(%_proxy) C(%_dlldata) : <toolset>msvc ;
1419         generators.override msvc.compile.idl : midl.compile.idl ;
1420
1421         generators.register-standard msvc.compile.mc : MC : H RC : <toolset>msvc ;
1422         generators.override msvc.compile.mc : mc.compile ;
1423
1424         # Note: the 'H' source type will catch both '.h' and '.hpp' headers as
1425         # the latter have their HPP type derived from H. The type of compilation
1426         # is determined entirely by the destination type.
1427         generators.register [ new msvc-pch-generator msvc.compile.c.pch   : H :   C_PCH OBJ : <pch>on <toolset>msvc ] ;
1428         generators.register [ new msvc-pch-generator msvc.compile.c++.pch : H : CPP_PCH OBJ : <pch>on <toolset>msvc ] ;
1429
1430         generators.override msvc.compile.c.pch   : pch.default-c-pch-generator ;
1431         generators.override msvc.compile.c++.pch : pch.default-cpp-pch-generator ;
1432     }
1433
1434     toolset.flags msvc.compile PCH_FILE   <pch>on : <pch-file>   ;
1435     toolset.flags msvc.compile PCH_SOURCE <pch>on : <pch-source> ;
1436     toolset.flags msvc.compile PCH_HEADER <pch>on : <pch-header> ;
1437
1438     #
1439     # Declare flags for compilation.
1440     #
1441
1442     toolset.flags msvc.compile CFLAGS <optimization>speed : /O2 ;
1443     toolset.flags msvc.compile CFLAGS <optimization>space : /O1 ;
1444
1445     toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium) : /G1 ;
1446     toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium2) : /G2 ;
1447
1448     toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>object : /Z7 ;
1449     toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>database : /Zi ;
1450     toolset.flags msvc.compile CFLAGS <optimization>off : /Od ;
1451     toolset.flags msvc.compile CFLAGS <inlining>off : /Ob0 ;
1452     toolset.flags msvc.compile CFLAGS <inlining>on : /Ob1 ;
1453     toolset.flags msvc.compile CFLAGS <inlining>full : /Ob2 ;
1454
1455     toolset.flags msvc.compile CFLAGS <warnings>on : /W3 ;
1456     toolset.flags msvc.compile CFLAGS <warnings>off : /W0 ;
1457     toolset.flags msvc.compile CFLAGS <warnings>all : /W4 ;
1458     toolset.flags msvc.compile CFLAGS <warnings-as-errors>on : /WX ;
1459
1460     toolset.flags msvc.compile C++FLAGS  <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>off : /EHs ;
1461     toolset.flags msvc.compile C++FLAGS  <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>on : /EHsc ;
1462     toolset.flags msvc.compile C++FLAGS  <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>off : /EHa ;
1463     toolset.flags msvc.compile C++FLAGS  <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>on : /EHac ;
1464
1465     # By default 8.0 enables rtti support while prior versions disabled it. We
1466     # simply enable or disable it explicitly so we do not have to depend on this
1467     # default behaviour.
1468     toolset.flags msvc.compile CFLAGS <rtti>on : /GR ;
1469     toolset.flags msvc.compile CFLAGS <rtti>off : /GR- ;
1470     toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>shared : /MD ;
1471     toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>shared : /MDd ;
1472
1473     toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>static/<threading>multi : /MT ;
1474     toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>static/<threading>multi : /MTd ;
1475
1476     toolset.flags msvc.compile OPTIONS <cflags> : ;
1477     toolset.flags msvc.compile.c++ OPTIONS <cxxflags> : ;
1478
1479     toolset.flags msvc.compile PDB_CFLAG <debug-symbols>on/<debug-store>database : /Fd ;
1480
1481     toolset.flags msvc.compile DEFINES <define> ;
1482     toolset.flags msvc.compile UNDEFS <undef> ;
1483     toolset.flags msvc.compile INCLUDES <include> ;
1484
1485     # Declare flags for the assembler.
1486     toolset.flags msvc.compile.asm USER_ASMFLAGS <asmflags> ;
1487
1488     toolset.flags msvc.compile.asm ASMFLAGS <debug-symbols>on : "/Zi /Zd" ;
1489
1490     toolset.flags msvc.compile.asm ASMFLAGS <warnings>on : /W3 ;
1491     toolset.flags msvc.compile.asm ASMFLAGS <warnings>off : /W0 ;
1492     toolset.flags msvc.compile.asm ASMFLAGS <warnings>all : /W4 ;
1493     toolset.flags msvc.compile.asm ASMFLAGS <warnings-as-errors>on : /WX ;
1494
1495     toolset.flags msvc.compile.asm DEFINES <define> ;
1496
1497     # Declare flags for linking.
1498     {
1499         toolset.flags msvc.link PDB_LINKFLAG <debug-symbols>on/<debug-store>database : /PDB: ;  # not used yet
1500         toolset.flags msvc.link LINKFLAGS <debug-symbols>on : /DEBUG ;
1501         toolset.flags msvc.link DEF_FILE <def-file> ;
1502
1503         # The linker disables the default optimizations when using /DEBUG so we
1504         # have to enable them manually for release builds with debug symbols.
1505         toolset.flags msvc LINKFLAGS <debug-symbols>on/<runtime-debugging>off : /OPT:REF,ICF ;
1506
1507         toolset.flags msvc LINKFLAGS <user-interface>console : /subsystem:console ;
1508         toolset.flags msvc LINKFLAGS <user-interface>gui : /subsystem:windows ;
1509         toolset.flags msvc LINKFLAGS <user-interface>wince : /subsystem:windowsce ;
1510         toolset.flags msvc LINKFLAGS <user-interface>native : /subsystem:native ;
1511         toolset.flags msvc LINKFLAGS <user-interface>auto : /subsystem:posix ;
1512
1513         toolset.flags msvc.link OPTIONS <linkflags> ;
1514         toolset.flags msvc.link LINKPATH <library-path> ;
1515
1516         toolset.flags msvc.link FINDLIBS_ST <find-static-library> ;
1517         toolset.flags msvc.link FINDLIBS_SA <find-shared-library> ;
1518         toolset.flags msvc.link LIBRARY_OPTION <toolset>msvc : "" : unchecked ;
1519         toolset.flags msvc.link LIBRARIES_MENTIONED_BY_FILE : <library-file> ;
1520         
1521         toolset.flags msvc.link.dll LINKFLAGS <suppress-import-lib>true : /NOENTRY ;
1522     }
1523
1524     toolset.flags msvc.archive AROPTIONS <archiveflags> ;
1525 }
1526
1527
1528 # Locates the requested setup script under the given folder and returns its full
1529 # path or nothing in case the script can not be found. In case multiple scripts
1530 # are found only the first one is returned.
1531 #
1532 # TODO: There used to exist a code comment for the msvc.init rule stating that
1533 # we do not correctly detect the location of the vcvars32.bat setup script for
1534 # the free VC7.1 tools in case user explicitly provides a path. This should be
1535 # tested or simply remove this whole comment in case this toolset version is no
1536 # longer important.
1537 #
1538 local rule locate-default-setup ( command : parent : setup-name )
1539 {
1540     local result = [ GLOB $(command) $(parent) : $(setup-name) ] ;
1541     if $(result[1])
1542     {
1543         return $(result[1]) ;
1544     }
1545 }
1546
1547
1548 # Validates given path, registers found configuration and prints debug
1549 # information about it.
1550 #
1551 local rule register-configuration ( version : path ? )
1552 {
1553     if $(path)
1554     {
1555         local command = [ GLOB $(path) : cl.exe ] ;
1556
1557         if $(command)
1558         {
1559             if $(.debug-configuration)
1560             {
1561                 ECHO notice: [msvc-cfg] msvc-$(version) detected, command:
1562                     '$(command)' ;
1563             }
1564
1565             $(.versions).register $(version) ;
1566             $(.versions).set $(version) : options : <command>$(command) ;
1567         }
1568     }
1569 }
1570
1571
1572 ################################################################################
1573 #
1574 #   Startup code executed when loading this module.
1575 #
1576 ################################################################################
1577
1578 if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
1579 {
1580     .debug-configuration = true ;
1581 }
1582
1583 # Miscellaneous constants.
1584 .RM = [ common.rm-command ] ;
1585 .nl = "
1586 " ;
1587 .ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ;
1588 .escaped-double-quote = "\"" ;
1589 .TOUCH_FILE = [ common.file-touch-command ] ;
1590
1591 # List of all registered configurations.
1592 .versions = [ new configurations ] ;
1593
1594 # Supported CPU architectures.
1595 .cpu-arch-i386 =
1596     <architecture>/<address-model>
1597     <architecture>/<address-model>32
1598     <architecture>x86/<address-model>
1599     <architecture>x86/<address-model>32 ;
1600
1601 .cpu-arch-amd64 =
1602     <architecture>/<address-model>64
1603     <architecture>x86/<address-model>64 ;
1604
1605 .cpu-arch-ia64 =
1606     <architecture>ia64/<address-model>
1607     <architecture>ia64/<address-model>64 ;
1608
1609 .cpu-arch-arm =
1610     <architecture>arm/<address-model>
1611     <architecture>arm/<address-model>32 ;
1612
1613
1614 # Supported CPU types (only Itanium optimization options are supported from
1615 # VC++ 2005 on). See
1616 # http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx for more
1617 # detailed information.
1618 .cpu-type-g5       = i586 pentium pentium-mmx ;
1619 .cpu-type-g6       = i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6
1620                      k6-2 k6-3 winchip-c6 winchip2 c3 c3-2 ;
1621 .cpu-type-em64t    = prescott nocona core2 corei7 corei7-avx core-avx-i
1622                      conroe conroe-xe conroe-l allendale merom
1623                      merom-xe kentsfield kentsfield-xe penryn wolfdale
1624                      yorksfield nehalem sandy-bridge ivy-bridge haswell ;
1625 .cpu-type-amd64    = k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3
1626                      athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3
1627                      btver1 btver2 ;
1628 .cpu-type-g7       = pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp
1629                      athlon-mp $(.cpu-type-em64t) $(.cpu-type-amd64) ;
1630 .cpu-type-itanium  = itanium itanium1 merced ;
1631 .cpu-type-itanium2 = itanium2 mckinley ;
1632 .cpu-type-arm      = armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312
1633                      armv7 armv7s ;
1634
1635 # Known toolset versions, in order of preference.
1636 .known-versions = 14.1 14.0 12.0 11.0 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1
1637     7.1toolkit 7.0 6.0 ;
1638
1639 # Version aliases.
1640 .version-alias-6 = 6.0 ;
1641 .version-alias-6.5 = 6.0 ;
1642 .version-alias-7 = 7.0 ;
1643 .version-alias-8 = 8.0 ;
1644 .version-alias-9 = 9.0 ;
1645 .version-alias-10 = 10.0 ;
1646 .version-alias-11 = 11.0 ;
1647 .version-alias-12 = 12.0 ;
1648 .version-alias-14 = 14.0 ;
1649 .version-alias-14.1 = 14.1 ;
1650
1651 # Names of registry keys containing the Visual C++ installation path (relative
1652 # to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
1653 .version-6.0-reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++" ;
1654 .version-7.0-reg = "VisualStudio\\7.0\\Setup\\VC" ;
1655 .version-7.1-reg = "VisualStudio\\7.1\\Setup\\VC" ;
1656 .version-8.0-reg = "VisualStudio\\8.0\\Setup\\VC" ;
1657 .version-8.0express-reg = "VCExpress\\8.0\\Setup\\VC" ;
1658 .version-9.0-reg = "VisualStudio\\9.0\\Setup\\VC" ;
1659 .version-9.0express-reg = "VCExpress\\9.0\\Setup\\VC" ;
1660 .version-10.0-reg = "VisualStudio\\10.0\\Setup\\VC" ;
1661 .version-10.0express-reg = "VCExpress\\10.0\\Setup\\VC" ;
1662 .version-11.0-reg = "VisualStudio\\11.0\\Setup\\VC" ;
1663 .version-12.0-reg = "VisualStudio\\12.0\\Setup\\VC" ;
1664 .version-14.0-reg = "VisualStudio\\14.0\\Setup\\VC" ;
1665
1666 # Visual C++ Toolkit 2003 does not store its installation path in the registry.
1667 # The environment variable 'VCToolkitInstallDir' and the default installation
1668 # path will be checked instead.
1669 .version-7.1toolkit-path    = "Microsoft Visual C++ Toolkit 2003/bin" ;
1670 .version-7.1toolkit-env     = VCToolkitInstallDir ;
1671 # Visual Studio 2017 doesn't use a registry at all. And the suggested methods
1672 # of discovery involve having a compiled program. We can't do that as it would
1673 # make for a recursive discovery and build dependency cycle. So we search
1674 # paths for VS2017 (aka msvc >= 14.1).
1675 .version-14.1-path =
1676     "../../VC/Tools/MSVC/*/bin/Host*/*"
1677     "Microsoft Visual Studio/2017/*/VC/Tools/MSVC/*/bin/Host*/*"
1678     ;
1679 .version-14.1-env = VS150COMNTOOLS ProgramFiles ProgramFiles(x86) ;
1680
1681 # Auto-detect all the available msvc installations on the system.
1682 auto-detect-toolset-versions ;
1683
1684
1685 # And finally trigger the actual Boost Build toolset registration.
1686 register-toolset ;