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
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)
14 ################################################################################
16 # MSVC Boost Build toolset module.
17 # --------------------------------
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.
23 ################################################################################
25 import "class" : new ;
41 import virtual-target ;
44 type.register MANIFEST : manifest ;
45 feature.feature embed-manifest : on off : incidental propagated ;
46 feature.feature embed-manifest-file : : free dependency ;
48 type.register PDB : pdb ;
51 ################################################################################
55 ################################################################################
57 # Initialize a specific toolset version configuration. As the result, path to
58 # compiler and, possible, program names are set up, and will be used when that
59 # version of compiler is requested. For example, you might have:
61 # using msvc : 6.5 : cl.exe ;
62 # using msvc : 7.0 : Y:/foo/bar/cl.exe ;
64 # The version parameter may be omitted:
66 # using msvc : : Z:/foo/bar/cl.exe ;
68 # The following keywords have special meanings when specified as versions:
69 # - all - all detected but not yet used versions will be marked as used
70 # with their default options.
71 # - default - this is an equivalent to an empty version.
73 # Depending on a supplied version, detected configurations and presence 'cl.exe'
74 # in the path different results may be achieved. The following table describes
75 # the possible scenarios:
78 # Passed Nothing "x.y" detected, detected,
79 # version detected detected cl.exe in path cl.exe in path
81 # default Error Use "x.y" Create "default" Use "x.y"
82 # all None Use all None Use all
83 # x.y - Use "x.y" - Use "x.y"
84 # a.b Error Error Create "a.b" Create "a.b"
86 # "x.y" - refers to a detected version;
87 # "a.b" - refers to an undetected version.
89 # FIXME: Currently the command parameter and the <compiler> property parameter
90 # seem to overlap in duties. Remove this duplication. This seems to be related
91 # to why someone started preparing to replace init with configure rules.
94 # The msvc version being configured. When omitted the tools invoked when no
95 # explicit version is given will be configured.
98 # The command used to invoke the compiler. If not specified:
99 # - if version is given, default location for that version will be
102 # - if version is not given, default locations for MSVC 9.0, 8.0, 7.1, 7.0
103 # and 6.* will be searched
105 # - if compiler is not found in the default locations, PATH will be
109 # Options may include:
111 # All options shared by multiple toolset types as handled by the
112 # common.handle-options() rule, e.g. <cflags>, <compileflags>, <cxxflags>,
113 # <fflags> & <linkflags>.
120 # <resource-compiler>
121 # Exact tool names to be used by this msvc toolset configuration.
124 # Command through which to pipe the output of running the compiler.
125 # For example to pass the output to STLfilt.
128 # Global setup command to invoke before running any of the msvc tools.
129 # It will be passed additional option parameters depending on the actual
138 # Platform specific setup command to invoke before running any of the
139 # msvc tools used when builing a target for a specific platform, e.g.
140 # when building a 32 or 64 bit executable.
142 # <rewrite-setup-scripts>
143 # Whether to rewrite setup scripts. New scripts will be output in
144 # build tree and will be used instead of originals in build actions.
146 # * on - rewrite scripts, if they do not already exist (default)
147 # * always - always rewrite scripts, even if they already exist
148 # * off - use original setup scripts
154 options += <command>$(command) ;
156 configure $(version) : $(options) ;
160 # 'configure' is a newer version of 'init'. The parameter 'command' is passed as
161 # a part of the 'options' list. See the 'init' rule comment for more detailed
164 rule configure ( version ? : options * )
172 errors.error "MSVC toolset configuration: options should be"
173 "empty when '$(version)' is specified." ;
176 # Configure (i.e. mark as used) all registered versions.
177 local all-versions = [ $(.versions).all ] ;
180 if $(.debug-configuration)
182 ECHO "notice: [msvc-cfg] Asked to configure all registered"
183 "msvc toolset versions when there are none currently"
189 for local v in $(all-versions)
191 # Note that there is no need to skip already configured
192 # versions here as this will request configure-really rule
193 # to configure the version using default options which will
194 # in turn cause it to simply do nothing in case the version
195 # has already been configured.
196 configure-really $(v) ;
201 configure-really : $(options) ;
204 configure-really $(version) : $(options) ;
209 # Sets up flag definitions dependent on the compiler version used.
210 # - 'version' is the version of compiler in N.M format.
211 # - 'conditions' is the property set to be used as flag conditions.
212 # - 'toolset' is the toolset for which flag settings are to be defined.
213 # This makes the rule reusable for other msvc-option-compatible compilers.
215 rule configure-version-specific ( toolset : version : conditions )
217 toolset.push-checking-for-flags-module unchecked ;
218 # Starting with versions 7.0, the msvc compiler have the /Zc:forScope and
219 # /Zc:wchar_t options that improve C++ standard conformance, but those
220 # options are off by default. If we are sure that the msvc version is at
221 # 7.*, add those options explicitly. We can be sure either if user specified
222 # version 7.* explicitly or if we auto-detected the version ourselves.
223 if ! [ MATCH ^(6\\.) : $(version) ]
225 toolset.flags $(toolset).compile CFLAGS $(conditions) : "/Zc:forScope" "/Zc:wchar_t" ;
226 toolset.flags $(toolset).compile.c++ C++FLAGS $(conditions) : /wd4675 ;
228 # Explicitly disable the 'function is deprecated' warning. Some msvc
229 # versions have a bug, causing them to emit the deprecation warning even
231 toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>off : /wd4996 ;
233 if [ MATCH "^([78]\\.)" : $(version) ]
235 # 64-bit compatibility warning deprecated since 9.0, see
236 # http://msdn.microsoft.com/en-us/library/yt4xw8fh.aspx
237 toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>all : /Wp64 ;
242 # Processor-specific optimization.
245 if [ MATCH "^([67])" : $(version) ]
247 # 8.0 deprecates some of the options.
248 toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed $(conditions)/<optimization>space : /Ogiy /Gs ;
249 toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed : /Ot ;
250 toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>space : /Os ;
252 toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set> : /GB ;
253 toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>i486 : /G4 ;
254 toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g5) : /G5 ;
255 toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g6) : /G6 ;
256 toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g7) : /G7 ;
258 # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math"
260 toolset.flags $(toolset).compile CFLAGS $(conditions) : /Op ;
262 # 7.1 and below have single-threaded static RTL.
263 toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>off/<runtime-link>static/<threading>single : /ML ;
264 toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>on/<runtime-link>static/<threading>single : /MLd ;
268 # 8.0 and above adds some more options.
269 toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set> : "/favor:blend" ;
270 toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set>$(.cpu-type-em64t) : "/favor:EM64T" ;
271 toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set>$(.cpu-type-amd64) : "/favor:AMD64" ;
273 # 8.0 and above only has multi-threaded static RTL.
274 toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>off/<runtime-link>static/<threading>single : /MT ;
275 toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>on/<runtime-link>static/<threading>single : /MTd ;
277 # Specify target machine type so the linker will not need to guess.
278 toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-amd64) : "/MACHINE:X64" ;
279 toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-i386) : "/MACHINE:X86" ;
280 toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-ia64) : "/MACHINE:IA64" ;
281 toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-arm) : "/MACHINE:ARM" ;
283 # Make sure that manifest will be generated even if there is no
284 # dependencies to put there.
285 toolset.flags $(toolset).link LINKFLAGS $(conditions) : /MANIFEST ;
288 toolset.pop-checking-for-flags-module ;
291 # Feature for handling targeting different Windows API sets.
292 feature.feature windows-api : desktop store phone : propagated composite link-incompatible ;
293 feature.compose <windows-api>store : <define>WINAPI_FAMILY=WINAPI_FAMILY_APP <define>_WIN32_WINNT=0x0602
294 <linkflags>/APPCONTAINER ;
295 feature.compose <windows-api>phone : <define>WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP <define>_WIN32_WINNT=0x0602
296 <linkflags>/APPCONTAINER <linkflags>"/NODEFAULTLIB:ole32.lib" <linkflags>"/NODEFAULTLIB:kernel32.lib" <linkflags>WindowsPhoneCore.lib ;
297 feature.set-default windows-api : desktop ;
300 # Registers this toolset including all of its flags, features & generators. Does
301 # nothing on repeated calls.
303 rule register-toolset ( )
305 if ! msvc in [ feature.values toolset ]
307 register-toolset-really ;
311 rule resolve-possible-msvc-version-alias ( version )
313 if $(.version-alias-$(version))
315 version = $(.version-alias-$(version)) ;
321 # Declare action for creating static libraries. If library exists, remove it
322 # before adding files. See
323 # http://article.gmane.org/gmane.comp.lib.boost.build/4241 for rationale.
326 # The 'DEL' command would issue a message to stdout if the file does not
327 # exist, so need a check.
330 if exist "$(<[1])" DEL "$(<[1])"
331 $(.SETUP) $(.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")"
339 $(.SETUP) $(.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")"
343 rule compile.asm ( targets + : sources * : properties * )
345 set-setup-command $(targets) : $(properties) ;
348 # For the assembler the following options are turned on by default:
350 # -Zp4 align structures to 4 bytes
351 # -Cp preserve case of user identifiers
352 # -Cx preserve case in publics, externs
356 $(.SETUP) $(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)"
360 rule compile.c ( targets + : sources * : properties * )
362 set-setup-command $(targets) : $(properties) ;
363 C++FLAGS on $(targets[1]) = ;
364 get-rspline $(targets) : -TC ;
365 compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
369 rule compile.c.preprocess ( targets + : sources * : properties * )
371 set-setup-command $(targets) : $(properties) ;
372 C++FLAGS on $(targets[1]) = ;
373 get-rspline $(targets) : -TC ;
374 preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
378 rule compile.c.pch ( targets + : sources * : properties * )
380 set-setup-command $(targets) : $(properties) ;
381 C++FLAGS on $(targets[1]) = ;
382 get-rspline $(targets[1]) : -TC ;
383 get-rspline $(targets[2]) : -TC ;
384 local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
387 DEPENDS $(<) : $(pch-source) ;
388 compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
392 compile-c-c++-pch $(targets) : $(sources) ;
396 toolset.flags msvc YLOPTION : "-Yl" ;
398 # Action for running the C/C++ compiler without using precompiled headers.
400 # WARNING: Synchronize any changes this in action with intel-win
402 # Notes regarding PDB generation, for when we use
403 # <debug-symbols>on/<debug-store>database:
405 # 1. PDB_CFLAG is only set for <debug-symbols>on/<debug-store>database, ensuring
406 # that the /Fd flag is dropped if PDB_CFLAG is empty.
408 # 2. When compiling executables's source files, PDB_NAME is set on a per-source
409 # file basis by rule compile-c-c++. The linker will pull these into the
412 # 3. When compiling library's source files, PDB_NAME is updated to <libname>.pdb
413 # for each source file by rule archive, as in this case compiler must be used
414 # to create a single PDB for our library.
416 actions compile-c-c++ bind PDB_NAME
418 $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER)
421 actions preprocess-c-c++ bind PDB_NAME
423 $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)"
426 rule compile-c-c++ ( targets + : sources * )
428 DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ;
429 DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
430 PDB_NAME on $(<) = $(<[1]:S=.pdb) ;
431 LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
434 rule preprocess-c-c++ ( targets + : sources * )
436 DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ;
437 DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
438 PDB_NAME on $(<) = $(<:S=.pdb) ;
439 LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
442 # Action for running the C/C++ compiler using precompiled headers. In addition
443 # to whatever else it needs to compile, this action also adds a temporary source
444 # .cpp file used to compile the precompiled headers themselves.
446 # The global .escaped-double-quote variable is used to avoid messing up Emacs
447 # syntax highlighting in the messy N-quoted code below.
448 actions compile-c-c++-pch
450 $(.SETUP) $(.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)
454 # Action for running the C/C++ compiler using precompiled headers. An already
455 # built source file for compiling the precompiled headers is expected to be
456 # given as one of the source parameters.
457 actions compile-c-c++-pch-s
459 $(.SETUP) $(.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)
463 rule compile.c++ ( targets + : sources * : properties * )
465 set-setup-command $(targets) : $(properties) ;
466 get-rspline $(targets) : -TP ;
467 compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
470 rule compile.c++.preprocess ( targets + : sources * : properties * )
472 set-setup-command $(targets) : $(properties) ;
473 get-rspline $(targets) : -TP ;
474 preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
478 rule compile.c++.pch ( targets + : sources * : properties * )
480 set-setup-command $(targets) : $(properties) ;
481 get-rspline $(targets[1]) : -TP ;
482 get-rspline $(targets[2]) : -TP ;
483 local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
486 DEPENDS $(<) : $(pch-source) ;
487 compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
491 compile-c-c++-pch $(targets) : $(sources) ;
495 rule compile.idl ( targets + : sources * : properties * )
497 set-setup-command $(targets) : $(properties) ;
500 # See midl.jam for details.
504 $(.SETUP) $(.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)")"
505 $(.TOUCH_FILE) "$(<[4]:W)"
506 $(.TOUCH_FILE) "$(<[5]:W)"
509 rule compile.mc ( targets + : sources * : properties * )
511 set-setup-command $(targets) : $(properties) ;
516 $(.SETUP) $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"
520 rule compile.rc ( targets + : sources * : properties * )
522 set-setup-command $(targets) : $(properties) ;
527 $(.SETUP) $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)"
530 toolset.uses-features msvc.link : <embed-manifest> <embed-manifest-file> ;
532 rule link ( targets + : sources * : properties * )
534 set-setup-command $(targets) : $(properties) ;
535 if <embed-manifest>on in $(properties)
537 if [ feature.get-values <embed-manifest-file> : $(properties) ]
539 DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ;
540 msvc.manifest.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ;
544 msvc.manifest $(targets) : $(sources) : $(properties) ;
549 rule link.dll ( targets + : sources * : properties * )
551 set-setup-command $(targets) : $(properties) ;
552 DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
554 if ! <suppress-import-lib>true in $(properties)
556 import-lib = $(targets[2]) ;
557 IMPORT_LIB on $(targets) = $(import-lib) ;
559 # On msvc-14.1, the linker might not touch the import library
560 # if the exports do not change. (Apparently this could also
561 # happen for incremental linking, which is why we disable it,
562 # but that no longer seems to be enough).
563 # Therefore, don't update the import library just because
564 # it's out-dated. It will be force updated, when the dll
565 # is updated. Also, make it so that anything that depends
566 # on it depends on the dll as well.
567 NOUPDATE $(import-lib) ;
568 INCLUDES $(import-lib) : $(targets[1]) ;
569 if <embed-manifest>on in $(properties)
571 if [ feature.get-values <embed-manifest-file> : $(properties) ]
573 DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ;
574 msvc.manifest.dll.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ;
578 msvc.manifest.dll $(targets) : $(sources) : $(properties) ;
583 # Incremental linking a DLL causes no end of problems: if the actual exports do
584 # not change, the import .lib file is never updated. Therefore, the .lib is
585 # always out-of-date and gets rebuilt every time. I am not sure that incremental
586 # linking is such a great idea in general, but in this case I am sure we do not
589 # Windows manifest is a new way to specify dependencies on managed DotNet
590 # assemblies and Windows native DLLs. The manifests are embedded as resources
591 # and are useful in any PE target (both DLL and EXE).
595 actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
597 $(.SETUP) $(.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")"
598 if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%
603 if exist "$(<[1]).manifest" (
604 $(.SETUP) $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
608 actions manifest.user bind EMBED_MANIFEST_FILE
610 $(.SETUP) $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);1"
613 actions link.dll bind IMPORT_LIB DEF_FILE LIBRARIES_MENTIONED_BY_FILE
615 $(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(IMPORT_LIB: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")"
616 if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%
621 if exist "$(<[1]).manifest" (
622 $(.SETUP) $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
625 actions manifest.dll.user bind EMBED_MANIFEST_FILE
627 $(.SETUP) $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2"
632 actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
634 $(.SETUP) $(.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")"
639 if test -e "$(<[1]).manifest"; then
640 $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);1"
644 actions link.dll bind IMPORT_LIB DEF_FILE LIBRARIES_MENTIONED_BY_FILE
646 $(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(IMPORT_LIB: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")"
651 if test -e "$(<[1]).manifest"; then
652 $(.SETUP) $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2"
656 actions manifest.dll.user bind EMBED_MANIFEST_FILE
658 $(.SETUP) $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2"
662 # This rule sets up the pdb file that will be used when generating static
663 # libraries and the debug-store option is database, so that the compiler puts
664 # all the debug info into a single .pdb file named after the library.
666 # Poking at source targets this way is probably not clean, but it is the
669 rule archive ( targets + : sources * : properties * )
671 set-setup-command $(targets) : $(properties) ;
672 PDB_NAME on $(>) = $(<[1]:S=.pdb) ;
673 LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
677 ################################################################################
681 ################################################################################
683 class msvc-pch-generator : pch-generator
685 import property-set ;
687 rule run-pch ( project name ? : property-set : sources * )
689 # Searching for the header and source file in the sources.
692 for local s in $(sources)
694 if [ type.is-derived [ $(s).type ] H ]
699 [ type.is-derived [ $(s).type ] CPP ] ||
700 [ type.is-derived [ $(s).type ] C ]
708 import errors : user-error : errors.user-error ;
709 errors.user-error "can not build pch without pch-header" ;
712 # If we do not have the PCH source - that is fine. We will just create a
713 # temporary .cpp file in the action.
715 local generated = [ generator.run $(project) $(name)
716 : [ property-set.create
717 # Passing of <pch-source> is a dirty trick, needed because
718 # non-composing generators with multiple inputs are subtly
719 # broken. For more detailed information see:
720 # https://zigzag.cs.msu.su:7813/boost.build/ticket/111
721 <pch-source>$(pch-source)
722 [ $(property-set).raw ] ]
726 for local g in $(generated[2-])
728 if [ type.is-derived [ $(g).type ] PCH ]
734 return [ $(generated[1]).add-raw <pch-header>$(pch-header)
735 <pch-file>$(pch-file) ] $(generated[2-]) ;
740 ################################################################################
744 ################################################################################
746 # Detects versions listed as '.known-versions' by checking registry information,
747 # environment variables & default paths. Supports both native Windows and
750 local rule auto-detect-toolset-versions ( )
752 if [ os.name ] in NT CYGWIN
754 # Get installation paths from the registry.
755 for local i in $(.known-versions)
757 if $(.version-$(i)-reg)
760 for local x in "" "Wow6432Node\\"
762 vc-path += [ W32_GETREG
763 "HKEY_LOCAL_MACHINE\\SOFTWARE\\"$(x)"\\Microsoft\\"$(.version-$(i)-reg)
769 vc-path = [ path.join [ path.make-NT $(vc-path[1]) ] "bin" ] ;
770 register-configuration $(i) : [ path.native $(vc-path[1]) ] ;
776 # Check environment and default installation paths.
777 for local i in $(.known-versions)
779 if ! $(i) in [ $(.versions).all ]
781 register-configuration $(i) : [ default-path $(i) ] ;
786 actions write-setup-script
788 @($(STDOUT):E=$(FILE_CONTENTS:J=$(.nl))) > "$(<)"
793 local rule call-batch-script ( command )
795 return "call $(command) >nul$(.nl)" ;
800 # On cygwin, we need to run both the batch script
801 # and the following command in the same instance
803 local rule call-batch-script ( command )
805 return "cmd.exe /S /C call $(command) \">nul\" \"&&\" " ;
809 # Local helper rule to create the vcvars setup command for given architecture
812 local rule generate-setup-cmd ( version : command : parent : options * : cpu : global-setup ? : default-global-setup-options : default-setup )
814 local setup-options ;
815 local setup = [ feature.get-values <setup-$(cpu)> : $(options) ] ;
817 if ! $(setup)-is-defined
819 if $(global-setup)-is-defined
821 setup = $(global-setup) ;
823 # If needed we can easily add using configuration flags
824 # here for overriding which options get passed to the
825 # global setup command for which target platform:
826 # setup-options = [ feature.get-values <setup-options-$(c)> : $(options) ] ;
827 setup-options ?= $(default-global-setup-options) ;
831 if [ MATCH "(14.1)" : $(version) ]
833 if $(.debug-configuration)
835 ECHO 'notice\: "[generate-setup-cmd]" $(version) is 14.1' ;
837 parent = [ path.native [ path.join $(parent) "..\\..\\..\\..\\..\\Auxiliary\\Build" ] ] ;
839 setup = [ locate-default-setup $(command) : $(parent) : $(default-setup) ] ;
840 setup ?= [ path.join $(parent) "vcvarsall.bat" ] ;
844 return $(setup) "$(setup-options:J= )" ;
847 # Worker for set-setup-command. Usable in a virtual-target.action.
848 rule adjust-setup-command ( new-setup : setup : properties * )
850 local internal = $(new-setup:S=.read) ;
851 NOTFILE $(internal) ;
852 local setup-options = [ property.select <msvc.setup-options> : $(properties) ] ;
853 setup-options = $(setup-options:G=:E=) ;
854 DEPENDS $(internal) : $(setup) ;
855 DEPENDS $(new-setup) : $(internal) ;
856 REBUILDS $(new-setup) : $(internal) ;
857 msvc.read-setup $(internal) : $(setup) ;
858 msvc.write-setup-script $(new-setup) : $(setup) ;
859 __ACTION_RULE__ on $(internal) = msvc.rewrite-setup $(setup) $(setup-options) $(new-setup) ;
862 # This doesn't actually do anything. It's merely
863 # used as a trigger for __ACTION_RULE__.
864 actions quietly read-setup { }
866 # Calculates the changes to the environment make by setup-script
867 # Should be used as a callback for __ACTION_RULE__
868 local rule rewrite-setup ( setup-script setup-options new-setup : target : * )
870 local setup-path = [ on $(setup-script) return $(LOCATE) $(SEARCH) ] ;
871 setup-path = $(setup-path[1]) ;
872 local command = "\"$(setup-script:G=:R=$(setup-path))\" $(setup-options)" ;
873 local original-vars = [ SPLIT_BY_CHARACTERS [ SHELL set ] : "\n" ] ;
874 local new-vars = [ SPLIT_BY_CHARACTERS [ SHELL "$(command) >nul && set" ] : "\n" ] ;
875 local diff-vars = [ set.difference $(new-vars) : $(original-vars) ] ;
878 FILE_CONTENTS on $(new-setup) = "REM $(command)" "SET "$(diff-vars) ;
882 IMPORT msvc : rewrite-setup : : msvc.rewrite-setup ;
884 # Helper rule to generate a faster alternative to MSVC setup scripts.
885 # We used to call MSVC setup scripts directly in every action, however in
886 # newer MSVC versions (10.0+) they make long-lasting registry queries
887 # which have a significant impact on build time.
888 local rule set-setup-command ( targets * : properties * )
890 if ! [ on $(targets) return $(.SETUP) ]
892 local setup-script = [ on $(targets) return $(.SETUP-SCRIPT) ] ;
893 local setup-options = [ on $(targets) return $(.SETUP-OPTIONS) ] ;
894 local key = .setup-command-$(setup-script:E=)-$(setup-options:E=) ;
897 properties = [ feature.expand $(properties) ] ;
898 properties = [ property.select <toolset> <toolset-msvc:version> <architecture> <address-model> <windows-api> <relevant> : $(properties) ] ;
899 local ps = [ property-set.create $(properties) <msvc.setup-options>$(setup-options) ] ;
900 local original = [ virtual-target.from-file $(setup-script) : [ path.pwd ] : $(.project) ] ;
901 local action = [ new non-scanning-action $(original) : msvc.adjust-setup-command : $(ps) ] ;
902 local new-setup = [ virtual-target.register [ new file-target msvc-setup.bat exact : : $(.project) : $(action) ] ] ;
903 local command = [ $(new-setup).actualize ] ;
904 local path = [ on $(command) return $(LOCATE) ] ;
905 local block-update = $(command:S=.nup) ;
906 NOUPDATE $(block-update) ;
907 NOTFILE $(block-update) ;
908 DEPENDS $(block-update) : $(command) ;
909 if [ on $(targets) return $(.REWRITE-SETUP) ]
913 $(key) = [ call-batch-script "\"$(command:WG=:R=$(path))\" $(setup-options:E=)" ] $(block-update) ;
915 DEPENDS $(targets) : $($(key)[2]) ;
916 .SETUP on $(targets) = $($(key)[1]) ;
920 # Worker rule for toolset version configuration. Takes an explicit version id or
921 # nothing in case it should configure the default toolset version (the first
922 # registered one or a new 'default' one in case no toolset versions have been
925 local rule configure-really ( version ? : options * )
927 local v = $(version) ;
929 # Decide what the 'default' version is.
932 # Take the best registered (i.e. auto-detected) version.
933 version = [ $(.versions).all ] ;
934 for local known in $(.known-versions)
936 if $(known) in $(version)
942 version = $(version[1]) ;
945 # Note: 'version' can still be empty at this point if no versions have
946 # been auto-detected.
947 version ?= "default" ;
950 # Version alias -> real version number.
951 version = [ resolve-possible-msvc-version-alias $(version) ] ;
953 # Check whether the selected configuration is already in use.
954 if $(version) in [ $(.versions).used ]
956 # Allow multiple 'toolset.using' calls for the same configuration if the
957 # identical sets of options are used.
958 if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] )
961 errors.error "MSVC toolset configuration: Toolset version"
962 "'$(version)' already configured." ;
967 # Register a new configuration.
968 $(.versions).register $(version) ;
970 # Add user-supplied to auto-detected options.
971 options = [ $(.versions).get $(version) : options ] $(options) ;
973 # Mark the configuration as 'used'.
974 $(.versions).use $(version) ;
976 # Generate conditions and save them.
977 local conditions = [ common.check-init-parameters msvc : version $(v) ]
980 $(.versions).set $(version) : conditions : $(conditions) ;
982 local command = [ feature.get-values <command> : $(options) ] ;
984 # For 14.1 we need the exact version as MS is planning rolling updates
985 # that will cause our `setup-cmd` to become invalid
986 exact-version = [ MATCH "(14\.10\.[0-9\.]+)" : $(command) ] ;
988 # If version is specified, we try to search first in default paths, and
990 command = [ common.get-invocation-command msvc : cl.exe : $(command) :
991 [ default-paths $(version) ] : $(version) ] ;
993 if ( ! $(version) || $(version) = "default" ) && ! $(command:D)
997 "Did not find command for MSVC toolset."
998 "If you have Visual Studio 2017 installed you will need to"
999 "specify the full path to the command,"
1000 "set VS150COMNTOOLS for your installation,"
1002 "build from the 'Visual Studio Command Prompt for VS 2017'."
1007 common.handle-options msvc : $(conditions) : $(command) : $(options) ;
1011 # Even if version is not explicitly specified, try to detect the
1012 # version from the path.
1013 # FIXME: We currently detect both Microsoft Visual Studio 9.0 and
1014 # 9.0express as 9.0 here.
1015 if [ MATCH "(MSVC\\14.1)" : $(command) ]
1019 else if [ MATCH "(Microsoft Visual Studio 14)" : $(command) ]
1023 else if [ MATCH "(Microsoft Visual Studio 12)" : $(command) ]
1027 else if [ MATCH "(Microsoft Visual Studio 11)" : $(command) ]
1031 else if [ MATCH "(Microsoft Visual Studio 10)" : $(command) ]
1035 else if [ MATCH "(Microsoft Visual Studio 9)" : $(command) ]
1039 else if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ]
1043 else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ]
1047 else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" :
1050 version = 7.1toolkit ;
1052 else if [ MATCH "(.NET[\/\\]VC7)" : $(command) ]
1062 # Generate and register setup command.
1064 local below-8.0 = [ MATCH "^([67]\\.)" : $(version) ] ;
1065 local below-11.0 = [ MATCH "^([6789]\\.|10\\.)" : $(version) ] ;
1067 local cpu = i386 amd64 ia64 arm ;
1072 else if $(below-11.0)
1074 cpu = i386 amd64 ia64 ;
1081 local setup-phone-i386 ;
1082 local setup-phone-arm ;
1086 # TODO: Note that if we specify a non-existant toolset version then
1087 # this rule may find and use a corresponding compiler executable
1088 # belonging to an incorrect toolset version. For example, if you
1089 # have only MSVC 7.1 installed, have its executable on the path and
1090 # specify you want Boost Build to use MSVC 9.0, then you want Boost
1091 # Build to report an error but this may cause it to silently use the
1092 # MSVC 7.1 compiler even though it thinks it is using the msvc-9.0
1094 command = [ common.get-absolute-tool-path $(command[-1]) ] ;
1099 local parent = [ path.make $(command) ] ;
1100 parent = [ path.parent $(parent) ] ;
1101 parent = [ path.native $(parent) ] ;
1103 # Setup will be used if the command name has been specified. If
1104 # setup is not specified explicitly then a default setup script will
1105 # be used instead. Setup scripts may be global or architecture/
1106 # /platform/cpu specific. Setup options are used only in case of
1107 # global setup scripts.
1109 # Default setup scripts provided with different VC distributions:
1111 # VC 7.1 had only the vcvars32.bat script specific to 32 bit i386
1112 # builds. It was located in the bin folder for the regular version
1113 # and in the root folder for the free VC 7.1 tools.
1115 # Later 8.0 & 9.0 versions introduce separate platform specific
1116 # vcvars*.bat scripts (e.g. 32 bit, 64 bit AMD or 64 bit Itanium)
1117 # located in or under the bin folder. Most also include a global
1118 # vcvarsall.bat helper script located in the root folder which runs
1119 # one of the aforementioned vcvars*.bat scripts based on the options
1120 # passed to it. So far only the version coming with some PlatformSDK
1121 # distributions does not include this top level script but to
1122 # support those we need to fall back to using the worker scripts
1123 # directly in case the top level script can not be found.
1125 local global-setup = [ feature.get-values <setup> : $(options) ] ;
1126 global-setup = $(global-setup[1]) ;
1127 local global-setup-phone = $(global-setup) ;
1130 global-setup ?= [ locate-default-setup $(command) : $(parent) :
1134 local default-setup-amd64 = vcvarsx86_amd64.bat ;
1135 local default-setup-i386 = vcvars32.bat ;
1136 local default-setup-ia64 = vcvarsx86_ia64.bat ;
1137 local default-setup-arm = vcvarsx86_arm.bat ;
1138 local default-setup-phone-i386 = vcvarsphonex86.bat ;
1139 local default-setup-phone-arm = vcvarsphonex86_arm.bat ;
1141 # http://msdn2.microsoft.com/en-us/library/x4d2c09s(VS.80).aspx and
1142 # http://msdn2.microsoft.com/en-us/library/x4d2c09s(vs.90).aspx
1143 # mention an x86_IPF option, that seems to be a documentation bug
1144 # and x86_ia64 is the correct option.
1145 local default-global-setup-options-amd64 = x86_amd64 ;
1146 local default-global-setup-options-i386 = x86 ;
1147 local default-global-setup-options-ia64 = x86_ia64 ;
1148 local default-global-setup-options-arm = x86_arm ;
1150 # When using 64-bit Windows, and targeting 64-bit, it is possible to
1151 # use a native 64-bit compiler, selected by the "amd64" & "ia64"
1152 # parameters to vcvarsall.bat. There are two variables we can use --
1153 # PROCESSOR_ARCHITECTURE and PROCESSOR_IDENTIFIER. The first is
1154 # 'x86' when running 32-bit Windows, no matter which processor is
1155 # used, and 'AMD64' on 64-bit windows on x86 (either AMD64 or EM64T)
1158 if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITECTURE ] ]
1160 default-global-setup-options-amd64 = amd64 ;
1162 # When Boost.Build itself is running as a 32-bit process on 64-bit
1163 # Windows, the above test will fail (since WOW64 simulates a 32-bit
1164 # environment, including environment values). So check the WOW64
1165 # variable PROCESSOR_ARCHITEW6432 as well.
1166 if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITEW6432 ] ]
1168 default-global-setup-options-amd64 = amd64 ;
1170 # TODO: The same 'native compiler usage' should be implemented for
1171 # the Itanium platform by using the "ia64" parameter. For this
1172 # though we need someone with access to this platform who can find
1173 # out how to correctly detect this case.
1174 else if $(somehow-detect-the-itanium-platform)
1176 default-global-setup-options-ia64 = ia64 ;
1179 for local c in $(cpu)
1181 exact-version ?= $(version) ;
1182 setup-$(c) = [ generate-setup-cmd $(exact-version) : $(command) : $(parent) : $(options) : $(c) : $(global-setup) : $(default-global-setup-options-$(c)) : $(default-setup-$(c)) ] ;
1185 # Windows phone has different setup scripts, located in a different directory hierarchy.
1186 # The 11.0 toolset can target Windows Phone 8.0 and the 12.0 toolset can target Windows Phone 8.1,
1187 # each of which have a different directory for their vcvars setup scripts.
1188 local phone-parent = [ path.native [ path.join $(parent) WPSDK ] ] ;
1189 local phone-directory = $(phone-parent) ;
1190 if [ MATCH "(11.0)" : $(version) ]
1192 phone-directory = [ path.native [ path.join $(phone-directory) WP80 ] ] ;
1194 else if [ MATCH "(12.0)" : $(version) ]
1196 phone-directory = [ path.native [ path.join $(phone-directory) WP81 ] ] ;
1198 global-setup-phone ?= [ locate-default-setup $(phone-directory) : $(phone-parent) : vcvarsphoneall.bat ] ;
1200 # If can't locate default phone setup script then this VS version doesn't support Windows Phone.
1201 if $(global-setup-phone)-is-defined
1203 # i386 CPU is for the Windows Phone emulator in Visual Studio.
1204 local phone-cpu = i386 arm ;
1205 for local c in $(phone-cpu)
1207 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)) ] ;
1212 # Get tool names (if any) and finish setup.
1214 compiler = [ feature.get-values <compiler> : $(options) ] ;
1217 linker = [ feature.get-values <linker> : $(options) ] ;
1220 resource-compiler = [ feature.get-values <resource-compiler> : $(options) ] ;
1221 resource-compiler ?= rc ;
1223 # Turn on some options for i386 assembler
1224 # -coff generate COFF format object file (compatible with cl.exe output)
1225 local default-assembler-amd64 = ml64 ;
1226 local default-assembler-i386 = "ml -coff" ;
1227 local default-assembler-ia64 = ias ;
1228 local default-assembler-ia64 = armasm ;
1230 assembler = [ feature.get-values <assembler> : $(options) ] ;
1232 idl-compiler = [ feature.get-values <idl-compiler> : $(options) ] ;
1233 idl-compiler ?= midl ;
1235 mc-compiler = [ feature.get-values <mc-compiler> : $(options) ] ;
1238 manifest-tool = [ feature.get-values <manifest-tool> : $(options) ] ;
1239 manifest-tool ?= mt ;
1241 local cc-filter = [ feature.get-values <compiler-filter> : $(options) ]
1244 for local c in $(cpu)
1246 # Setup script is not required in some configurations.
1249 local cpu-conditions = $(conditions)/$(.cpu-arch-$(c)) ;
1251 if $(.debug-configuration)
1253 for local cpu-condition in $(cpu-conditions)
1255 ECHO "notice: [msvc-cfg] condition: '$(cpu-condition)', setup: '$(setup-$(c))'" ;
1259 local cpu-assembler = $(assembler) ;
1260 cpu-assembler ?= $(default-assembler-$(c)) ;
1262 for local api in desktop store phone
1264 local setup-script = $(setup-$(c)) ;
1267 setup-script = $(setup-phone-$(c)) ;
1270 if <rewrite-setup-scripts>always in $(options)
1272 toolset.flags msvc .REWRITE-SETUP <windows-api>$(api)/$(cpu-conditions) : true ;
1275 if ! $(setup-script)
1277 # Should we try to set up some error handling or fallbacks here?
1279 else if <rewrite-setup-scripts>off in $(options) || [ os.name ] != NT
1281 toolset.flags msvc .SETUP <windows-api>$(api)/$(cpu-conditions) : [ call-batch-script "\"$(setup-script[1]:W)\" $(setup-script[2-]:E=)" ] ;
1285 toolset.flags msvc .SETUP-SCRIPT <windows-api>$(api)/$(cpu-conditions) : $(setup-script[1]) ;
1286 toolset.flags msvc .SETUP-OPTIONS <windows-api>$(api)/$(cpu-conditions) : $(setup-script[2-]) ;
1289 toolset.flags msvc.compile .RC <windows-api>$(api)/$(cpu-conditions) : $(resource-compiler) ;
1290 toolset.flags msvc.compile .IDL <windows-api>$(api)/$(cpu-conditions) : $(idl-compiler) ;
1291 toolset.flags msvc.compile .MC <windows-api>$(api)/$(cpu-conditions) : $(mc-compiler) ;
1292 toolset.flags msvc.link .MT <windows-api>$(api)/$(cpu-conditions) : $(manifest-tool) -nologo ;
1296 toolset.flags msvc.compile .CC <windows-api>$(api)/$(cpu-conditions) : $(compiler) /Zm800 -nologo ;
1300 toolset.flags msvc.compile .CC <windows-api>$(api)/$(cpu-conditions) : $(compiler) /Zm800 /ZW /EHsc -nologo ;
1302 toolset.flags msvc.compile .ASM <windows-api>$(api)/$(cpu-conditions) : $(cpu-assembler) -nologo ;
1303 toolset.flags msvc.link .LD <windows-api>$(api)/$(cpu-conditions) : $(linker) /NOLOGO "/INCREMENTAL:NO" ;
1304 toolset.flags msvc.archive .LD <windows-api>$(api)/$(cpu-conditions) : $(linker) /lib /NOLOGO ;
1309 toolset.flags msvc .CC.FILTER $(cpu-conditions) : "|" $(cc-filter) ;
1313 # Starting with Visual Studio 2013 the CRT is split into a desktop and app dll.
1314 # If targeting WinRT and 12.0 set lib path to link against app CRT.
1315 if [ MATCH "(12)" : $(version) ]
1317 local storeLibPath = [ path.join $(parent) "lib/store" ] ;
1318 toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-i386) : [ path.native $(storeLibPath) ] ;
1319 toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-amd64) : [ path.native [ path.join $(storeLibPath) "amd64" ] ] ;
1320 toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-arm) : [ path.native [ path.join $(storeLibPath) "arm" ] ] ;
1323 # Set version-specific flags.
1324 configure-version-specific msvc : $(version) : $(conditions) ;
1329 # Returns the default installation path for the given version.
1331 local rule default-path ( version )
1333 # Use auto-detected path if possible.
1334 local result = [ feature.get-values <command> : [ $(.versions).get $(version)
1339 result = $(result:D) ;
1343 # try to use vswhere
1344 local pseudo_env_VS150 ;
1345 if $(version) = 14.1 || $(version) = "default"
1347 local req = "-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64" ;
1348 local prop = "-property installationPath" ;
1349 local limit = "-version \"[15.0,16.0)\"" ;
1350 local root = [ os.environ "ProgramFiles(x86)" ] ;
1353 root = [ os.environ "ProgramFiles" ] ;
1355 local vswhere = "$(root)\\Microsoft Visual Studio\\Installer\\vswhere.exe" ;
1356 if ( [ path.exists $(vswhere) ] )
1358 local vmwhere_cmd = "\"$(vswhere)\" -latest -products * $(req) $(prop) $(limit)" ;
1359 local shell_ret = [ SPLIT_BY_CHARACTERS [ SHELL $(vmwhere_cmd) ] : "\n" ] ;
1360 pseudo_env_VS150 = [ path.native [ path.join $(shell_ret) "\\Common7\\Tools" ] ] ;
1364 # Check environment or previous path_VS150
1365 for local env in $(.version-$(version)-env)
1368 if ( $(pseudo_env_VS150) && [ path.exists $(pseudo_env_VS150) ] )
1370 env-path = $(pseudo_env_VS150) ;
1374 env-path = [ os.environ $(env) ] ;
1376 if $(env-path) && $(.version-$(version)-path)
1378 for local bin-path in $(.version-$(version)-path)
1380 result = [ path.glob [ path.make $(env-path) ] : $(bin-path) ] ;
1383 result = [ path.native $(result[1]) ] ;
1399 # Returns either the default installation path (if 'version' is not empty) or
1400 # list of all known default paths (if no version is given)
1402 local rule default-paths ( version ? )
1404 local possible-paths ;
1408 possible-paths += [ default-path $(version) ] ;
1412 for local i in $(.known-versions)
1414 possible-paths += [ default-path $(i) ] ;
1418 return $(possible-paths) ;
1422 rule get-rspline ( target : lang-opt )
1424 CC_RSPLINE on $(target) = [ on $(target) return $(lang-opt) -U$(UNDEFS)
1425 $(CFLAGS) $(C++FLAGS) $(OPTIONS) -c $(.nl)-D$(DEFINES)
1426 $(.nl)\"-I$(INCLUDES:W)\" ] ;
1429 class msvc-linking-generator : linking-generator
1431 # Calls the base version. If necessary, also create a target for the
1432 # manifest file.specifying source's name as the name of the created
1433 # target. As result, the PCH will be named whatever.hpp.gch, and not
1435 rule generated-targets ( sources + : property-set : project name ? )
1437 local result = [ linking-generator.generated-targets $(sources)
1438 : $(property-set) : $(project) $(name) ] ;
1442 local name-main = [ $(result[1]).name ] ;
1443 local action = [ $(result[1]).action ] ;
1445 if [ $(property-set).get <debug-symbols> ] = "on"
1447 # We force the exact name on PDB. The reason is tagging -- the
1448 # tag rule may reasonably special case some target types, like
1449 # SHARED_LIB. The tag rule will not catch PDBs, and it cannot
1450 # even easily figure out if a PDB is paired with a SHARED_LIB,
1451 # EXE or something else. Because PDBs always get the same name
1452 # as the main target, with .pdb as extension, just force it.
1453 local target = [ class.new file-target $(name-main:S=.pdb) exact
1454 : PDB : $(project) : $(action) ] ;
1455 local registered-target = [ virtual-target.register $(target) ]
1457 if $(target) != $(registered-target)
1459 $(action).replace-targets $(target) : $(registered-target) ;
1461 result += $(registered-target) ;
1464 if [ $(property-set).get <embed-manifest> ] = "off"
1466 # Manifest is an evil target. It has .manifest appened to the
1467 # name of the main target, including extension, e.g.
1468 # a.exe.manifest. We use the 'exact' name to achieve this
1470 local target = [ class.new file-target $(name-main).manifest
1471 exact : MANIFEST : $(project) : $(action) ] ;
1472 local registered-target = [ virtual-target.register $(target) ]
1474 if $(target) != $(registered-target)
1476 $(action).replace-targets $(target) : $(registered-target) ;
1478 result += $(registered-target) ;
1486 # Unsafe worker rule for the register-toolset() rule. Must not be called
1489 local rule register-toolset-really ( )
1491 feature.extend toolset : msvc ;
1493 # Intel and msvc supposedly have link-compatible objects.
1494 feature.subfeature toolset msvc : vendor : intel : propagated optional ;
1496 # Inherit MIDL flags.
1497 toolset.inherit-flags msvc : midl ;
1500 toolset.inherit-flags msvc : mc ;
1502 # Dynamic runtime comes only in MT flavour.
1503 toolset.add-requirements
1504 <toolset>msvc,<runtime-link>shared:<threading>multi ;
1506 # Declare msvc toolset specific features.
1508 feature.feature debug-store : object database : propagated ;
1509 feature.feature pch-source : : dependency free ;
1512 # Declare generators.
1514 # TODO: Is it possible to combine these? Make the generators
1515 # non-composing so that they do not convert each source into a separate
1517 generators.register [ new msvc-linking-generator msvc.link :
1518 OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : <toolset>msvc ] ;
1519 generators.register [ new msvc-linking-generator msvc.link.dll :
1520 OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB :
1521 <toolset>msvc <suppress-import-lib>false ] ;
1522 generators.register [ new msvc-linking-generator msvc.link.dll :
1523 OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB :
1524 <toolset>msvc <suppress-import-lib>true ] ;
1526 generators.register-archiver msvc.archive : OBJ : STATIC_LIB : <toolset>msvc ;
1527 generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : <toolset>msvc ;
1528 generators.register-c-compiler msvc.compile.c : C : OBJ : <toolset>msvc ;
1529 generators.register-c-compiler msvc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : <toolset>msvc ;
1530 generators.register-c-compiler msvc.compile.c.preprocess : C : PREPROCESSED_C : <toolset>msvc ;
1532 # Using 'register-c-compiler' adds the build directory to INCLUDES.
1533 generators.register-c-compiler msvc.compile.rc : RC : OBJ(%_res) : <toolset>msvc ;
1534 generators.override msvc.compile.rc : rc.compile.resource ;
1535 generators.register-standard msvc.compile.asm : ASM : OBJ : <toolset>msvc ;
1537 generators.register-c-compiler msvc.compile.idl : IDL : MSTYPELIB H C(%_i) C(%_proxy) C(%_dlldata) : <toolset>msvc ;
1538 generators.override msvc.compile.idl : midl.compile.idl ;
1540 generators.register-standard msvc.compile.mc : MC : H RC : <toolset>msvc ;
1541 generators.override msvc.compile.mc : mc.compile ;
1543 # Note: the 'H' source type will catch both '.h' and '.hpp' headers as
1544 # the latter have their HPP type derived from H. The type of compilation
1545 # is determined entirely by the destination type.
1546 generators.register [ new msvc-pch-generator msvc.compile.c.pch : H : C_PCH OBJ : <pch>on <toolset>msvc ] ;
1547 generators.register [ new msvc-pch-generator msvc.compile.c++.pch : H : CPP_PCH OBJ : <pch>on <toolset>msvc ] ;
1549 generators.override msvc.compile.c.pch : pch.default-c-pch-generator ;
1550 generators.override msvc.compile.c++.pch : pch.default-cpp-pch-generator ;
1553 toolset.flags msvc.compile PCH_FILE <pch>on : <pch-file> ;
1554 toolset.flags msvc.compile PCH_SOURCE <pch>on : <pch-source> ;
1555 toolset.flags msvc.compile PCH_HEADER <pch>on : <pch-header> ;
1558 # Declare flags for compilation.
1561 toolset.flags msvc.compile CFLAGS <optimization>speed : /O2 ;
1562 toolset.flags msvc.compile CFLAGS <optimization>space : /O1 ;
1564 toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium) : /G1 ;
1565 toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium2) : /G2 ;
1567 toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>object : /Z7 ;
1568 toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>database : /Zi ;
1569 toolset.flags msvc.compile CFLAGS <optimization>off : /Od ;
1570 toolset.flags msvc.compile CFLAGS <inlining>off : /Ob0 ;
1571 toolset.flags msvc.compile CFLAGS <inlining>on : /Ob1 ;
1572 toolset.flags msvc.compile CFLAGS <inlining>full : /Ob2 ;
1574 toolset.flags msvc.compile CFLAGS <warnings>on : /W3 ;
1575 toolset.flags msvc.compile CFLAGS <warnings>off : /W0 ;
1576 toolset.flags msvc.compile CFLAGS <warnings>all : /W4 ;
1577 toolset.flags msvc.compile CFLAGS <warnings-as-errors>on : /WX ;
1579 toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>off : /EHs ;
1580 toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>on : /EHsc ;
1581 toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>off : /EHa ;
1582 toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>on : /EHac ;
1584 toolset.flags msvc.compile C++FLAGS <cxxstd>14 : "/std:c++14" ;
1585 toolset.flags msvc.compile C++FLAGS <cxxstd>17 : "/std:c++17" ;
1586 toolset.flags msvc.compile C++FLAGS <cxxstd>latest : "/std:c++latest" ;
1588 # By default 8.0 enables rtti support while prior versions disabled it. We
1589 # simply enable or disable it explicitly so we do not have to depend on this
1590 # default behaviour.
1591 toolset.flags msvc.compile CFLAGS <rtti>on : /GR ;
1592 toolset.flags msvc.compile CFLAGS <rtti>off : /GR- ;
1593 toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>shared : /MD ;
1594 toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>shared : /MDd ;
1596 toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>static/<threading>multi : /MT ;
1597 toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>static/<threading>multi : /MTd ;
1599 toolset.flags msvc.compile OPTIONS <cflags> : ;
1600 toolset.flags msvc.compile.c++ OPTIONS <cxxflags> : ;
1602 toolset.flags msvc.compile PDB_CFLAG <debug-symbols>on/<debug-store>database : /Fd ;
1604 toolset.flags msvc.compile DEFINES <define> ;
1605 toolset.flags msvc.compile UNDEFS <undef> ;
1606 toolset.flags msvc.compile INCLUDES <include> ;
1608 # Declare flags for the assembler.
1609 toolset.flags msvc.compile.asm USER_ASMFLAGS <asmflags> ;
1611 toolset.flags msvc.compile.asm ASMFLAGS <debug-symbols>on : "/Zi /Zd" ;
1613 toolset.flags msvc.compile.asm ASMFLAGS <warnings>on : /W3 ;
1614 toolset.flags msvc.compile.asm ASMFLAGS <warnings>off : /W0 ;
1615 toolset.flags msvc.compile.asm ASMFLAGS <warnings>all : /W4 ;
1616 toolset.flags msvc.compile.asm ASMFLAGS <warnings-as-errors>on : /WX ;
1618 toolset.flags msvc.compile.asm DEFINES <define> ;
1620 # Declare flags for linking.
1622 toolset.flags msvc.link PDB_LINKFLAG <debug-symbols>on/<debug-store>database : "/PDB:" ; # not used yet
1623 toolset.flags msvc.link LINKFLAGS <debug-symbols>on : /DEBUG ;
1624 toolset.flags msvc.link DEF_FILE <def-file> ;
1626 # The linker disables the default optimizations when using /DEBUG so we
1627 # have to enable them manually for release builds with debug symbols.
1628 toolset.flags msvc LINKFLAGS <debug-symbols>on/<runtime-debugging>off : "/OPT:REF,ICF" ;
1630 toolset.flags msvc LINKFLAGS <user-interface>console : "/subsystem:console" ;
1631 toolset.flags msvc LINKFLAGS <user-interface>gui : "/subsystem:windows" ;
1632 toolset.flags msvc LINKFLAGS <user-interface>wince : "/subsystem:windowsce" ;
1633 toolset.flags msvc LINKFLAGS <user-interface>native : "/subsystem:native" ;
1634 toolset.flags msvc LINKFLAGS <user-interface>auto : "/subsystem:posix" ;
1636 toolset.flags msvc.link OPTIONS <linkflags> ;
1637 toolset.flags msvc.link LINKPATH <library-path> ;
1639 toolset.flags msvc.link FINDLIBS_ST <find-static-library> ;
1640 toolset.flags msvc.link FINDLIBS_SA <find-shared-library> ;
1641 toolset.flags msvc.link LIBRARY_OPTION <toolset>msvc : "" : unchecked ;
1642 toolset.flags msvc.link LIBRARIES_MENTIONED_BY_FILE : <library-file> ;
1644 toolset.flags msvc.link.dll LINKFLAGS <suppress-import-lib>true : /NOENTRY ;
1647 toolset.flags msvc.archive AROPTIONS <archiveflags> ;
1649 # Create a project to allow building the setup scripts
1650 project.initialize $(__name__) ;
1651 .project = [ project.current ] ;
1654 feature.feature msvc.setup-options : : free ;
1658 # Locates the requested setup script under the given folder and returns its full
1659 # path or nothing in case the script can not be found. In case multiple scripts
1660 # are found only the first one is returned.
1662 # TODO: There used to exist a code comment for the msvc.init rule stating that
1663 # we do not correctly detect the location of the vcvars32.bat setup script for
1664 # the free VC7.1 tools in case user explicitly provides a path. This should be
1665 # tested or simply remove this whole comment in case this toolset version is no
1668 local rule locate-default-setup ( command : parent : setup-name )
1670 local result = [ GLOB $(command) $(parent) : $(setup-name) ] ;
1673 return $(result[1]) ;
1678 # Validates given path, registers found configuration and prints debug
1679 # information about it.
1681 local rule register-configuration ( version : path ? )
1685 local command = [ GLOB $(path) : cl.exe ] ;
1689 if $(.debug-configuration)
1691 ECHO notice\: "[msvc-cfg]" msvc-$(version) detected, command\:
1695 $(.versions).register $(version) ;
1696 $(.versions).set $(version) : options : <command>$(command) ;
1702 ################################################################################
1704 # Startup code executed when loading this module.
1706 ################################################################################
1708 if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
1710 .debug-configuration = true ;
1713 # Miscellaneous constants.
1714 .RM = [ common.rm-command ] ;
1717 .ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ;
1718 .escaped-double-quote = "\"" ;
1719 .TOUCH_FILE = [ common.file-touch-command ] ;
1721 # List of all registered configurations.
1722 .versions = [ new configurations ] ;
1724 # Supported CPU architectures.
1726 <architecture>/<address-model>
1727 <architecture>/<address-model>32
1728 <architecture>x86/<address-model>
1729 <architecture>x86/<address-model>32 ;
1732 <architecture>/<address-model>64
1733 <architecture>x86/<address-model>64 ;
1736 <architecture>ia64/<address-model>
1737 <architecture>ia64/<address-model>64 ;
1740 <architecture>arm/<address-model>
1741 <architecture>arm/<address-model>32 ;
1744 # Supported CPU types (only Itanium optimization options are supported from
1745 # VC++ 2005 on). See
1746 # http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx for more
1747 # detailed information.
1748 .cpu-type-g5 = i586 pentium pentium-mmx ;
1749 .cpu-type-g6 = i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6
1750 k6-2 k6-3 winchip-c6 winchip2 c3 c3-2 ;
1751 .cpu-type-em64t = prescott nocona core2 corei7 corei7-avx core-avx-i
1752 conroe conroe-xe conroe-l allendale merom
1753 merom-xe kentsfield kentsfield-xe penryn wolfdale
1754 yorksfield nehalem sandy-bridge ivy-bridge haswell
1755 broadwell skylake skylake-avx512 cannonlake ;
1756 .cpu-type-amd64 = k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3
1757 athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3
1758 bdver4 btver1 btver2 znver1 ;
1759 .cpu-type-g7 = pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp
1760 athlon-mp $(.cpu-type-em64t) $(.cpu-type-amd64) ;
1761 .cpu-type-itanium = itanium itanium1 merced ;
1762 .cpu-type-itanium2 = itanium2 mckinley ;
1763 .cpu-type-arm = armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312
1766 # Known toolset versions, in order of preference.
1767 .known-versions = 14.1 14.0 12.0 11.0 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1
1768 7.1toolkit 7.0 6.0 ;
1771 .version-alias-6 = 6.0 ;
1772 .version-alias-6.5 = 6.0 ;
1773 .version-alias-7 = 7.0 ;
1774 .version-alias-8 = 8.0 ;
1775 .version-alias-9 = 9.0 ;
1776 .version-alias-10 = 10.0 ;
1777 .version-alias-11 = 11.0 ;
1778 .version-alias-12 = 12.0 ;
1779 .version-alias-14 = 14.0 ;
1780 .version-alias-14.1 = 14.1 ;
1782 # Names of registry keys containing the Visual C++ installation path (relative
1783 # to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
1784 .version-6.0-reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++" ;
1785 .version-7.0-reg = "VisualStudio\\7.0\\Setup\\VC" ;
1786 .version-7.1-reg = "VisualStudio\\7.1\\Setup\\VC" ;
1787 .version-8.0-reg = "VisualStudio\\8.0\\Setup\\VC" ;
1788 .version-8.0express-reg = "VCExpress\\8.0\\Setup\\VC" ;
1789 .version-9.0-reg = "VisualStudio\\9.0\\Setup\\VC" ;
1790 .version-9.0express-reg = "VCExpress\\9.0\\Setup\\VC" ;
1791 .version-10.0-reg = "VisualStudio\\10.0\\Setup\\VC" ;
1792 .version-10.0express-reg = "VCExpress\\10.0\\Setup\\VC" ;
1793 .version-11.0-reg = "VisualStudio\\11.0\\Setup\\VC" ;
1794 .version-12.0-reg = "VisualStudio\\12.0\\Setup\\VC" ;
1795 .version-14.0-reg = "VisualStudio\\14.0\\Setup\\VC" ;
1797 # Visual C++ Toolkit 2003 does not store its installation path in the registry.
1798 # The environment variable 'VCToolkitInstallDir' and the default installation
1799 # path will be checked instead.
1800 .version-7.1toolkit-path = "Microsoft Visual C++ Toolkit 2003/bin" ;
1801 .version-7.1toolkit-env = VCToolkitInstallDir ;
1802 # Visual Studio 2017 doesn't use a registry at all. And the suggested methods
1803 # of discovery involve having a compiled program. So as a fallback we search
1804 # paths for VS2017 (aka msvc >= 14.1).
1805 .version-14.1-path =
1806 "../../VC/Tools/MSVC/*/bin/Host*/*"
1807 "Microsoft Visual Studio/2017/*/VC/Tools/MSVC/*/bin/Host*/*"
1809 .version-14.1-env = VS150COMNTOOLS ProgramFiles ProgramFiles(x86) ;
1811 # Auto-detect all the available msvc installations on the system.
1812 auto-detect-toolset-versions ;
1815 # And finally trigger the actual Boost Build toolset registration.