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 type.register MANIFEST : manifest ;
42 feature.feature embed-manifest : on off : incidental propagated ;
43 feature.feature embed-manifest-file : : free dependency ;
45 type.register PDB : pdb ;
48 ################################################################################
52 ################################################################################
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:
58 # using msvc : 6.5 : cl.exe ;
59 # using msvc : 7.0 : Y:/foo/bar/cl.exe ;
61 # The version parameter may be omitted:
63 # using msvc : : Z:/foo/bar/cl.exe ;
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.
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:
75 # Passed Nothing "x.y" detected, detected,
76 # version detected detected cl.exe in path cl.exe in path
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"
83 # "x.y" - refers to a detected version;
84 # "a.b" - refers to an undetected version.
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.
91 # The msvc version being configured. When omitted the tools invoked when no
92 # explicit version is given will be configured.
95 # The command used to invoke the compiler. If not specified:
96 # - if version is given, default location for that version will be
99 # - if version is not given, default locations for MSVC 9.0, 8.0, 7.1, 7.0
100 # and 6.* will be searched
102 # - if compiler is not found in the default locations, PATH will be
106 # Options may include:
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>.
117 # <resource-compiler>
118 # Exact tool names to be used by this msvc toolset configuration.
121 # Command through which to pipe the output of running the compiler.
122 # For example to pass the output to STLfilt.
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
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.
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.
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
151 options += <command>$(command) ;
153 configure $(version) : $(options) ;
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
161 rule configure ( version ? : options * )
169 errors.error "MSVC toolset configuration: options should be"
170 "empty when '$(version)' is specified." ;
173 # Configure (i.e. mark as used) all registered versions.
174 local all-versions = [ $(.versions).all ] ;
177 if $(.debug-configuration)
179 ECHO "notice: [msvc-cfg] Asked to configure all registered"
180 "msvc toolset versions when there are none currently"
186 for local v in $(all-versions)
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) ;
198 configure-really : $(options) ;
201 configure-really $(version) : $(options) ;
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.
212 rule configure-version-specific ( toolset : version : conditions )
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) ]
222 toolset.flags $(toolset).compile CFLAGS $(conditions) : /Zc:forScope /Zc:wchar_t ;
223 toolset.flags $(toolset).compile.c++ C++FLAGS $(conditions) : /wd4675 ;
225 # Explicitly disable the 'function is deprecated' warning. Some msvc
226 # versions have a bug, causing them to emit the deprecation warning even
228 toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>off : /wd4996 ;
230 if [ MATCH ^([78]\\.) : $(version) ]
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 ;
239 # Processor-specific optimization.
242 if [ MATCH ^([67]) : $(version) ]
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 ;
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 ;
255 # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math"
257 toolset.flags $(toolset).compile CFLAGS $(conditions) : /Op ;
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 ;
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 ;
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 ;
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 ;
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 ;
285 toolset.pop-checking-for-flags-module ;
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 ;
297 # Registers this toolset including all of its flags, features & generators. Does
298 # nothing on repeated calls.
300 rule register-toolset ( )
302 if ! msvc in [ feature.values toolset ]
304 register-toolset-really ;
308 rule resolve-possible-msvc-version-alias ( version )
310 if $(.version-alias-$(version))
312 version = $(.version-alias-$(version)) ;
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.
323 # The 'DEL' command would issue a message to stdout if the file does not
324 # exist, so need a check.
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")"
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")"
341 # For the assembler the following options are turned on by default:
343 # -Zp4 align structures to 4 bytes
344 # -Cp preserve case of user identifiers
345 # -Cx preserve case in publics, externs
349 $(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)"
353 rule compile.c ( targets + : sources * : properties * )
355 C++FLAGS on $(targets[1]) = ;
356 get-rspline $(targets) : -TC ;
357 compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
361 rule compile.c.preprocess ( targets + : sources * : properties * )
363 C++FLAGS on $(targets[1]) = ;
364 get-rspline $(targets) : -TC ;
365 preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
369 rule compile.c.pch ( targets + : sources * : properties * )
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) ] ;
377 DEPENDS $(<) : $(pch-source) ;
378 compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
382 compile-c-c++-pch $(targets) : $(sources) ;
386 toolset.flags msvc YLOPTION : "-Yl" ;
388 # Action for running the C/C++ compiler without using precompiled headers.
390 # WARNING: Synchronize any changes this in action with intel-win
392 # Notes regarding PDB generation, for when we use
393 # <debug-symbols>on/<debug-store>database:
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.
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
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.
406 actions compile-c-c++ bind PDB_NAME
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)
411 actions preprocess-c-c++ bind PDB_NAME
413 $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)"
416 rule compile-c-c++ ( targets + : sources * )
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) ] ;
424 rule preprocess-c-c++ ( targets + : sources * )
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) ] ;
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.
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
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)
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
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)
453 rule compile.c++ ( targets + : sources * : properties * )
455 get-rspline $(targets) : -TP ;
456 compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
459 rule compile.c++.preprocess ( targets + : sources * : properties * )
461 get-rspline $(targets) : -TP ;
462 preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
466 rule compile.c++.pch ( targets + : sources * : properties * )
468 get-rspline $(targets[1]) : -TP ;
469 get-rspline $(targets[2]) : -TP ;
470 local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
473 DEPENDS $(<) : $(pch-source) ;
474 compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
478 compile-c-c++-pch $(targets) : $(sources) ;
483 # See midl.jam for details.
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)"
495 $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"
501 $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)"
505 rule link ( targets + : sources * : properties * )
507 if <embed-manifest>on in $(properties)
509 if [ feature.get-values <embed-manifest-file> : $(properties) ]
511 DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ;
512 msvc.manifest.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ;
516 msvc.manifest $(targets) : $(sources) : $(properties) ;
521 rule link.dll ( targets + : sources * : properties * )
523 DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
524 if <embed-manifest>on in $(properties)
526 if [ feature.get-values <embed-manifest-file> : $(properties) ]
528 DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ;
529 msvc.manifest.dll.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ;
533 msvc.manifest.dll $(targets) : $(sources) : $(properties) ;
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
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).
550 actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
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%
558 if exist "$(<[1]).manifest" (
559 $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
563 actions manifest.user bind EMBED_MANIFEST_FILE
565 $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);1"
568 actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
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%
576 if exist "$(<[1]).manifest" (
577 $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
580 actions manifest.dll.user bind EMBED_MANIFEST_FILE
582 $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2"
587 actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
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")"
594 if test -e "$(<[1]).manifest"; then
595 $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);1"
599 actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE
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")"
606 if test -e "$(<[1]).manifest"; then
607 $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2"
611 actions manifest.dll.user bind EMBED_MANIFEST_FILE
613 $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2"
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.
621 # Poking at source targets this way is probably not clean, but it is the
624 rule archive ( targets + : sources * : properties * )
626 PDB_NAME on $(>) = $(<[1]:S=.pdb) ;
627 LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
631 ################################################################################
635 ################################################################################
637 class msvc-pch-generator : pch-generator
639 import property-set ;
641 rule run-pch ( project name ? : property-set : sources * )
643 # Searching for the header and source file in the sources.
646 for local s in $(sources)
648 if [ type.is-derived [ $(s).type ] H ]
653 [ type.is-derived [ $(s).type ] CPP ] ||
654 [ type.is-derived [ $(s).type ] C ]
662 import errors : user-error : errors.user-error ;
663 errors.user-error "can not build pch without pch-header" ;
666 # If we do not have the PCH source - that is fine. We will just create a
667 # temporary .cpp file in the action.
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 ] ]
680 for local g in $(generated)
682 if [ type.is-derived [ $(g).type ] PCH ]
688 return [ property-set.create <pch-header>$(pch-header)
689 <pch-file>$(pch-file) ] $(generated) ;
694 ################################################################################
698 ################################################################################
700 # Detects versions listed as '.known-versions' by checking registry information,
701 # environment variables & default paths. Supports both native Windows and
704 local rule auto-detect-toolset-versions ( )
706 if [ os.name ] in NT CYGWIN
708 # Get installation paths from the registry.
709 for local i in $(.known-versions)
711 if $(.version-$(i)-reg)
714 for local x in "" "Wow6432Node\\"
716 vc-path += [ W32_GETREG
717 "HKEY_LOCAL_MACHINE\\SOFTWARE\\"$(x)"\\Microsoft\\"$(.version-$(i)-reg)
723 vc-path = [ path.join [ path.make-NT $(vc-path[1]) ] "bin" ] ;
724 register-configuration $(i) : [ path.native $(vc-path[1]) ] ;
730 # Check environment and default installation paths.
731 for local i in $(.known-versions)
733 if ! $(i) in [ $(.versions).all ]
735 register-configuration $(i) : [ default-path $(i) ] ;
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 ? )
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 )
750 setup-script-id = b2_$(toolset)_$(version)_$(setup-script:B) ;
751 if $(setup-options)-is-not-empty
753 setup-script-id = $(setup-script-id)_$(setup-options) ;
756 if $(.$(setup-script-id))
758 errors.error rewriting setup script for the second time ;
761 local tmpdir = [ os.environ TEMP ] ;
762 local replacement = [ path.native $(tmpdir)/$(setup-script-id).cmd ] ;
763 if ( $(rewrite-setup) = always ) || ( ! [ path.exists $(replacement) ] )
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) ] ;
770 local target = <new-setup-script>$(replacement) ;
771 FILE_CONTENTS on $(target) = "SET "$(diff-vars) ;
773 msvc.write-setup-script $(target) ;
774 UPDATE_NOW $(target) : : ignore-minus-n ;
775 .$(setup-script-id) = $(replacement) ;
776 result = "\""$(replacement)"\"" ;
781 result = "\""$(replacement)"\"" ;
787 actions write-setup-script
789 @($(STDOUT):E=$(FILE_CONTENTS:J=$(.nl))) > "$(<)"
793 # Local helper rule to create the vcvars setup command for given architecture
796 local rule generate-setup-cmd ( version : command : parent : options * : cpu : global-setup ? : default-global-setup-options : default-setup )
798 local setup-prefix = "call " ;
799 local setup-suffix = " >nul"$(.nl) ;
800 if ! [ os.name ] in NT
802 setup-prefix = "cmd.exe /S /C call " ;
803 setup-suffix = " \">nul\" \"&&\" " ;
806 local setup-options ;
807 local setup = [ feature.get-values <setup-$(cpu)> : $(options) ] ;
809 if ! $(setup)-is-defined
811 if $(global-setup)-is-defined
813 setup = $(global-setup) ;
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) ;
823 if [ MATCH "(14.1)" : $(version) ]
825 if $(.debug-configuration)
827 ECHO 'notice: [generate-setup-cmd] $(version) is 14.1' ;
829 parent = [ path.native [ path.join $(parent) "..\\..\\..\\..\\..\\Auxiliary\\Build" ] ] ;
831 setup = [ locate-default-setup $(command) : $(parent) : $(default-setup) ] ;
832 setup ?= [ path.join $(parent) "vcvarsall.bat" ] ;
836 # Cygwin to Windows path translation.
837 setup = "\""$(setup:W)"\"" ;
839 # Append setup options to the setup name and add the final setup
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) ;
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
855 local rule configure-really ( version ? : options * )
857 local v = $(version) ;
859 # Decide what the 'default' version is.
862 # Take the best registered (i.e. auto-detected) version.
863 version = [ $(.versions).all ] ;
864 for local known in $(.known-versions)
866 if $(known) in $(version)
872 version = $(version[1]) ;
875 # Note: 'version' can still be empty at this point if no versions have
876 # been auto-detected.
877 version ?= "default" ;
880 # Version alias -> real version number.
881 version = [ resolve-possible-msvc-version-alias $(version) ] ;
883 # Check whether the selected configuration is already in use.
884 if $(version) in [ $(.versions).used ]
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 ] )
891 errors.error "MSVC toolset configuration: Toolset version"
892 "'$(version)' already configured." ;
897 # Register a new configuration.
898 $(.versions).register $(version) ;
900 # Add user-supplied to auto-detected options.
901 options = [ $(.versions).get $(version) : options ] $(options) ;
903 # Mark the configuration as 'used'.
904 $(.versions).use $(version) ;
906 # Generate conditions and save them.
907 local conditions = [ common.check-init-parameters msvc : version $(v) ]
910 $(.versions).set $(version) : conditions : $(conditions) ;
912 local command = [ feature.get-values <command> : $(options) ] ;
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) ] ;
918 # If version is specified, we try to search first in default paths, and
920 command = [ common.get-invocation-command msvc : cl.exe : $(command) :
921 [ default-paths $(version) ] : $(version) ] ;
923 if ( ! $(version) || $(version) = "default" ) && ! $(command:D)
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,"
932 "build from the 'Visual Studio Command Prompt for VS 2017'."
937 common.handle-options msvc : $(conditions) : $(command) : $(options) ;
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) ]
949 else if [ MATCH "(Microsoft Visual Studio 14)" : $(command) ]
953 else if [ MATCH "(Microsoft Visual Studio 12)" : $(command) ]
957 else if [ MATCH "(Microsoft Visual Studio 11)" : $(command) ]
961 else if [ MATCH "(Microsoft Visual Studio 10)" : $(command) ]
965 else if [ MATCH "(Microsoft Visual Studio 9)" : $(command) ]
969 else if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ]
973 else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ]
977 else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" :
980 version = 7.1toolkit ;
982 else if [ MATCH "(.NET[\/\\]VC7)" : $(command) ]
992 # Generate and register setup command.
994 local below-8.0 = [ MATCH ^([67]\\.) : $(version) ] ;
995 local below-11.0 = [ MATCH ^([6789]\\.|10\\.) : $(version) ] ;
997 local cpu = i386 amd64 ia64 arm ;
1002 else if $(below-11.0)
1004 cpu = i386 amd64 ia64 ;
1011 local setup-phone-i386 ;
1012 local setup-phone-arm ;
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
1024 command = [ common.get-absolute-tool-path $(command[-1]) ] ;
1029 local parent = [ path.make $(command) ] ;
1030 parent = [ path.parent $(parent) ] ;
1031 parent = [ path.native $(parent) ] ;
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.
1039 # Default setup scripts provided with different VC distributions:
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.
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.
1055 local global-setup = [ feature.get-values <setup> : $(options) ] ;
1056 global-setup = $(global-setup[1]) ;
1057 local global-setup-phone = $(global-setup) ;
1060 global-setup ?= [ locate-default-setup $(command) : $(parent) :
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 ;
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 ;
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)
1088 if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITECTURE ] ]
1090 default-global-setup-options-amd64 = amd64 ;
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 ] ]
1098 default-global-setup-options-amd64 = amd64 ;
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)
1106 default-global-setup-options-ia64 = ia64 ;
1109 for local c in $(cpu)
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)) ] ;
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) ]
1122 phone-directory = [ path.native [ path.join $(phone-directory) WP80 ] ] ;
1124 else if [ MATCH "(12.0)" : $(version) ]
1126 phone-directory = [ path.native [ path.join $(phone-directory) WP81 ] ] ;
1128 global-setup-phone ?= [ locate-default-setup $(phone-directory) : $(phone-parent) : vcvarsphoneall.bat ] ;
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
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)
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)) ] ;
1142 # Get tool names (if any) and finish setup.
1144 compiler = [ feature.get-values <compiler> : $(options) ] ;
1147 linker = [ feature.get-values <linker> : $(options) ] ;
1150 resource-compiler = [ feature.get-values <resource-compiler> : $(options) ] ;
1151 resource-compiler ?= rc ;
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 ;
1160 assembler = [ feature.get-values <assembler> : $(options) ] ;
1162 idl-compiler = [ feature.get-values <idl-compiler> : $(options) ] ;
1163 idl-compiler ?= midl ;
1165 mc-compiler = [ feature.get-values <mc-compiler> : $(options) ] ;
1168 manifest-tool = [ feature.get-values <manifest-tool> : $(options) ] ;
1169 manifest-tool ?= mt ;
1171 local cc-filter = [ feature.get-values <compiler-filter> : $(options) ]
1174 for local c in $(cpu)
1176 # Setup script is not required in some configurations.
1179 local cpu-conditions = $(conditions)/$(.cpu-arch-$(c)) ;
1181 if $(.debug-configuration)
1183 for local cpu-condition in $(cpu-conditions)
1185 ECHO "notice: [msvc-cfg] condition: '$(cpu-condition)', setup: '$(setup-$(c))'" ;
1189 local cpu-assembler = $(assembler) ;
1190 cpu-assembler ?= $(default-assembler-$(c)) ;
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 ;
1197 for api in desktop store phone
1199 local setup-script = $(setup-$(c)) ;
1202 setup-script = $(setup-phone-$(c)) ;
1206 toolset.flags msvc.compile .CC <windows-api>$(api)/$(cpu-conditions) : $(setup-script)$(compiler) /Zm800 -nologo ;
1210 toolset.flags msvc.compile .CC <windows-api>$(api)/$(cpu-conditions) : $(setup-script)$(compiler) /Zm800 /ZW /EHsc -nologo ;
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 ;
1219 toolset.flags msvc .CC.FILTER $(cpu-conditions) : "|" $(cc-filter) ;
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) ]
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" ] ] ;
1233 # Set version-specific flags.
1234 configure-version-specific msvc : $(version) : $(conditions) ;
1239 # Returns the default installation path for the given version.
1241 local rule default-path ( version )
1243 # Use auto-detected path if possible.
1244 local result = [ feature.get-values <command> : [ $(.versions).get $(version)
1249 result = $(result:D) ;
1253 # try to use vswhere
1254 local pseudo_env_VS150 ;
1255 if $(version) = 14.1 || $(version) = "default"
1257 local req = "-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64" ;
1258 local prop = "-property installationPath" ;
1259 local limit = "-version \"[15.0,16.0)\"" ;
1260 local root = [ os.environ "ProgramFiles(x86)" ] ;
1263 root = [ os.environ "ProgramFiles" ] ;
1265 local vswhere = "$(root)\\Microsoft Visual Studio\\Installer\\vswhere.exe" ;
1266 if ( [ path.exists $(vswhere) ] )
1268 local vmwhere_cmd = "\"$(vswhere)\" -latest -products * $(req) $(prop) $(limit)" ;
1269 local shell_ret = [ SPLIT_BY_CHARACTERS [ SHELL $(vmwhere_cmd) ] : "\n" ] ;
1270 pseudo_env_VS150 = [ path.native [ path.join $(shell_ret) "\\Common7\\Tools" ] ] ;
1274 # Check environment or previous path_VS150
1275 for local env in $(.version-$(version)-env)
1278 if ( $(pseudo_env_VS150) && [ path.exists $(pseudo_env_VS150) ] )
1280 env-path = $(pseudo_env_VS150) ;
1284 env-path = [ os.environ $(env) ] ;
1286 if $(env-path) && $(.version-$(version)-path)
1288 for local bin-path in $(.version-$(version)-path)
1290 result = [ path.glob [ path.make $(env-path) ] : $(bin-path) ] ;
1293 result = [ path.native $(result[1]) ] ;
1309 # Returns either the default installation path (if 'version' is not empty) or
1310 # list of all known default paths (if no version is given)
1312 local rule default-paths ( version ? )
1314 local possible-paths ;
1318 possible-paths += [ default-path $(version) ] ;
1322 for local i in $(.known-versions)
1324 possible-paths += [ default-path $(i) ] ;
1328 return $(possible-paths) ;
1332 rule get-rspline ( target : lang-opt )
1334 CC_RSPLINE on $(target) = [ on $(target) return $(lang-opt) -U$(UNDEFS)
1335 $(CFLAGS) $(C++FLAGS) $(OPTIONS) -c $(.nl)-D$(DEFINES)
1336 $(.nl)\"-I$(INCLUDES:W)\" ] ;
1339 class msvc-linking-generator : linking-generator
1341 # Calls the base version. If necessary, also create a target for the
1342 # manifest file.specifying source's name as the name of the created
1343 # target. As result, the PCH will be named whatever.hpp.gch, and not
1345 rule generated-targets ( sources + : property-set : project name ? )
1347 local result = [ linking-generator.generated-targets $(sources)
1348 : $(property-set) : $(project) $(name) ] ;
1352 local name-main = [ $(result[0]).name ] ;
1353 local action = [ $(result[0]).action ] ;
1355 if [ $(property-set).get <debug-symbols> ] = "on"
1357 # We force the exact name on PDB. The reason is tagging -- the
1358 # tag rule may reasonably special case some target types, like
1359 # SHARED_LIB. The tag rule will not catch PDBs, and it cannot
1360 # even easily figure out if a PDB is paired with a SHARED_LIB,
1361 # EXE or something else. Because PDBs always get the same name
1362 # as the main target, with .pdb as extension, just force it.
1363 local target = [ class.new file-target $(name-main:S=.pdb) exact
1364 : PDB : $(project) : $(action) ] ;
1365 local registered-target = [ virtual-target.register $(target) ]
1367 if $(target) != $(registered-target)
1369 $(action).replace-targets $(target) : $(registered-target) ;
1371 result += $(registered-target) ;
1374 if [ $(property-set).get <embed-manifest> ] = "off"
1376 # Manifest is an evil target. It has .manifest appened to the
1377 # name of the main target, including extension, e.g.
1378 # a.exe.manifest. We use the 'exact' name to achieve this
1380 local target = [ class.new file-target $(name-main).manifest
1381 exact : MANIFEST : $(project) : $(action) ] ;
1382 local registered-target = [ virtual-target.register $(target) ]
1384 if $(target) != $(registered-target)
1386 $(action).replace-targets $(target) : $(registered-target) ;
1388 result += $(registered-target) ;
1396 # Unsafe worker rule for the register-toolset() rule. Must not be called
1399 local rule register-toolset-really ( )
1401 feature.extend toolset : msvc ;
1403 # Intel and msvc supposedly have link-compatible objects.
1404 feature.subfeature toolset msvc : vendor : intel : propagated optional ;
1406 # Inherit MIDL flags.
1407 toolset.inherit-flags msvc : midl ;
1410 toolset.inherit-flags msvc : mc ;
1412 # Dynamic runtime comes only in MT flavour.
1413 toolset.add-requirements
1414 <toolset>msvc,<runtime-link>shared:<threading>multi ;
1416 # Declare msvc toolset specific features.
1418 feature.feature debug-store : object database : propagated ;
1419 feature.feature pch-source : : dependency free ;
1422 # Declare generators.
1424 # TODO: Is it possible to combine these? Make the generators
1425 # non-composing so that they do not convert each source into a separate
1427 generators.register [ new msvc-linking-generator msvc.link :
1428 OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : <toolset>msvc ] ;
1429 generators.register [ new msvc-linking-generator msvc.link.dll :
1430 OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB :
1431 <toolset>msvc <suppress-import-lib>false ] ;
1432 generators.register [ new msvc-linking-generator msvc.link.dll :
1433 OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB :
1434 <toolset>msvc <suppress-import-lib>true ] ;
1436 generators.register-archiver msvc.archive : OBJ : STATIC_LIB : <toolset>msvc ;
1437 generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : <toolset>msvc ;
1438 generators.register-c-compiler msvc.compile.c : C : OBJ : <toolset>msvc ;
1439 generators.register-c-compiler msvc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : <toolset>msvc ;
1440 generators.register-c-compiler msvc.compile.c.preprocess : C : PREPROCESSED_C : <toolset>msvc ;
1442 # Using 'register-c-compiler' adds the build directory to INCLUDES.
1443 generators.register-c-compiler msvc.compile.rc : RC : OBJ(%_res) : <toolset>msvc ;
1444 generators.override msvc.compile.rc : rc.compile.resource ;
1445 generators.register-standard msvc.compile.asm : ASM : OBJ : <toolset>msvc ;
1447 generators.register-c-compiler msvc.compile.idl : IDL : MSTYPELIB H C(%_i) C(%_proxy) C(%_dlldata) : <toolset>msvc ;
1448 generators.override msvc.compile.idl : midl.compile.idl ;
1450 generators.register-standard msvc.compile.mc : MC : H RC : <toolset>msvc ;
1451 generators.override msvc.compile.mc : mc.compile ;
1453 # Note: the 'H' source type will catch both '.h' and '.hpp' headers as
1454 # the latter have their HPP type derived from H. The type of compilation
1455 # is determined entirely by the destination type.
1456 generators.register [ new msvc-pch-generator msvc.compile.c.pch : H : C_PCH OBJ : <pch>on <toolset>msvc ] ;
1457 generators.register [ new msvc-pch-generator msvc.compile.c++.pch : H : CPP_PCH OBJ : <pch>on <toolset>msvc ] ;
1459 generators.override msvc.compile.c.pch : pch.default-c-pch-generator ;
1460 generators.override msvc.compile.c++.pch : pch.default-cpp-pch-generator ;
1463 toolset.flags msvc.compile PCH_FILE <pch>on : <pch-file> ;
1464 toolset.flags msvc.compile PCH_SOURCE <pch>on : <pch-source> ;
1465 toolset.flags msvc.compile PCH_HEADER <pch>on : <pch-header> ;
1468 # Declare flags for compilation.
1471 toolset.flags msvc.compile CFLAGS <optimization>speed : /O2 ;
1472 toolset.flags msvc.compile CFLAGS <optimization>space : /O1 ;
1474 toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium) : /G1 ;
1475 toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium2) : /G2 ;
1477 toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>object : /Z7 ;
1478 toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>database : /Zi ;
1479 toolset.flags msvc.compile CFLAGS <optimization>off : /Od ;
1480 toolset.flags msvc.compile CFLAGS <inlining>off : /Ob0 ;
1481 toolset.flags msvc.compile CFLAGS <inlining>on : /Ob1 ;
1482 toolset.flags msvc.compile CFLAGS <inlining>full : /Ob2 ;
1484 toolset.flags msvc.compile CFLAGS <warnings>on : /W3 ;
1485 toolset.flags msvc.compile CFLAGS <warnings>off : /W0 ;
1486 toolset.flags msvc.compile CFLAGS <warnings>all : /W4 ;
1487 toolset.flags msvc.compile CFLAGS <warnings-as-errors>on : /WX ;
1489 toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>off : /EHs ;
1490 toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>on : /EHsc ;
1491 toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>off : /EHa ;
1492 toolset.flags msvc.compile C++FLAGS <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>on : /EHac ;
1494 toolset.flags msvc.compile C++FLAGS <cxxstd>14 : /std:c++14 ;
1495 toolset.flags msvc.compile C++FLAGS <cxxstd>17 : /std:c++17 ;
1496 toolset.flags msvc.compile C++FLAGS <cxxstd>latest : /std:c++latest ;
1498 # By default 8.0 enables rtti support while prior versions disabled it. We
1499 # simply enable or disable it explicitly so we do not have to depend on this
1500 # default behaviour.
1501 toolset.flags msvc.compile CFLAGS <rtti>on : /GR ;
1502 toolset.flags msvc.compile CFLAGS <rtti>off : /GR- ;
1503 toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>shared : /MD ;
1504 toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>shared : /MDd ;
1506 toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>static/<threading>multi : /MT ;
1507 toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>static/<threading>multi : /MTd ;
1509 toolset.flags msvc.compile OPTIONS <cflags> : ;
1510 toolset.flags msvc.compile.c++ OPTIONS <cxxflags> : ;
1512 toolset.flags msvc.compile PDB_CFLAG <debug-symbols>on/<debug-store>database : /Fd ;
1514 toolset.flags msvc.compile DEFINES <define> ;
1515 toolset.flags msvc.compile UNDEFS <undef> ;
1516 toolset.flags msvc.compile INCLUDES <include> ;
1518 # Declare flags for the assembler.
1519 toolset.flags msvc.compile.asm USER_ASMFLAGS <asmflags> ;
1521 toolset.flags msvc.compile.asm ASMFLAGS <debug-symbols>on : "/Zi /Zd" ;
1523 toolset.flags msvc.compile.asm ASMFLAGS <warnings>on : /W3 ;
1524 toolset.flags msvc.compile.asm ASMFLAGS <warnings>off : /W0 ;
1525 toolset.flags msvc.compile.asm ASMFLAGS <warnings>all : /W4 ;
1526 toolset.flags msvc.compile.asm ASMFLAGS <warnings-as-errors>on : /WX ;
1528 toolset.flags msvc.compile.asm DEFINES <define> ;
1530 # Declare flags for linking.
1532 toolset.flags msvc.link PDB_LINKFLAG <debug-symbols>on/<debug-store>database : /PDB: ; # not used yet
1533 toolset.flags msvc.link LINKFLAGS <debug-symbols>on : /DEBUG ;
1534 toolset.flags msvc.link DEF_FILE <def-file> ;
1536 # The linker disables the default optimizations when using /DEBUG so we
1537 # have to enable them manually for release builds with debug symbols.
1538 toolset.flags msvc LINKFLAGS <debug-symbols>on/<runtime-debugging>off : /OPT:REF,ICF ;
1540 toolset.flags msvc LINKFLAGS <user-interface>console : /subsystem:console ;
1541 toolset.flags msvc LINKFLAGS <user-interface>gui : /subsystem:windows ;
1542 toolset.flags msvc LINKFLAGS <user-interface>wince : /subsystem:windowsce ;
1543 toolset.flags msvc LINKFLAGS <user-interface>native : /subsystem:native ;
1544 toolset.flags msvc LINKFLAGS <user-interface>auto : /subsystem:posix ;
1546 toolset.flags msvc.link OPTIONS <linkflags> ;
1547 toolset.flags msvc.link LINKPATH <library-path> ;
1549 toolset.flags msvc.link FINDLIBS_ST <find-static-library> ;
1550 toolset.flags msvc.link FINDLIBS_SA <find-shared-library> ;
1551 toolset.flags msvc.link LIBRARY_OPTION <toolset>msvc : "" : unchecked ;
1552 toolset.flags msvc.link LIBRARIES_MENTIONED_BY_FILE : <library-file> ;
1554 toolset.flags msvc.link.dll LINKFLAGS <suppress-import-lib>true : /NOENTRY ;
1557 toolset.flags msvc.archive AROPTIONS <archiveflags> ;
1561 # Locates the requested setup script under the given folder and returns its full
1562 # path or nothing in case the script can not be found. In case multiple scripts
1563 # are found only the first one is returned.
1565 # TODO: There used to exist a code comment for the msvc.init rule stating that
1566 # we do not correctly detect the location of the vcvars32.bat setup script for
1567 # the free VC7.1 tools in case user explicitly provides a path. This should be
1568 # tested or simply remove this whole comment in case this toolset version is no
1571 local rule locate-default-setup ( command : parent : setup-name )
1573 local result = [ GLOB $(command) $(parent) : $(setup-name) ] ;
1576 return $(result[1]) ;
1581 # Validates given path, registers found configuration and prints debug
1582 # information about it.
1584 local rule register-configuration ( version : path ? )
1588 local command = [ GLOB $(path) : cl.exe ] ;
1592 if $(.debug-configuration)
1594 ECHO notice: [msvc-cfg] msvc-$(version) detected, command:
1598 $(.versions).register $(version) ;
1599 $(.versions).set $(version) : options : <command>$(command) ;
1605 ################################################################################
1607 # Startup code executed when loading this module.
1609 ################################################################################
1611 if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
1613 .debug-configuration = true ;
1616 # Miscellaneous constants.
1617 .RM = [ common.rm-command ] ;
1620 .ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ;
1621 .escaped-double-quote = "\"" ;
1622 .TOUCH_FILE = [ common.file-touch-command ] ;
1624 # List of all registered configurations.
1625 .versions = [ new configurations ] ;
1627 # Supported CPU architectures.
1629 <architecture>/<address-model>
1630 <architecture>/<address-model>32
1631 <architecture>x86/<address-model>
1632 <architecture>x86/<address-model>32 ;
1635 <architecture>/<address-model>64
1636 <architecture>x86/<address-model>64 ;
1639 <architecture>ia64/<address-model>
1640 <architecture>ia64/<address-model>64 ;
1643 <architecture>arm/<address-model>
1644 <architecture>arm/<address-model>32 ;
1647 # Supported CPU types (only Itanium optimization options are supported from
1648 # VC++ 2005 on). See
1649 # http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx for more
1650 # detailed information.
1651 .cpu-type-g5 = i586 pentium pentium-mmx ;
1652 .cpu-type-g6 = i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6
1653 k6-2 k6-3 winchip-c6 winchip2 c3 c3-2 ;
1654 .cpu-type-em64t = prescott nocona core2 corei7 corei7-avx core-avx-i
1655 conroe conroe-xe conroe-l allendale merom
1656 merom-xe kentsfield kentsfield-xe penryn wolfdale
1657 yorksfield nehalem sandy-bridge ivy-bridge haswell
1658 broadwell skylake skylake-avx512 cannonlake ;
1659 .cpu-type-amd64 = k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3
1660 athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3
1661 bdver4 btver1 btver2 znver1 ;
1662 .cpu-type-g7 = pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp
1663 athlon-mp $(.cpu-type-em64t) $(.cpu-type-amd64) ;
1664 .cpu-type-itanium = itanium itanium1 merced ;
1665 .cpu-type-itanium2 = itanium2 mckinley ;
1666 .cpu-type-arm = armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312
1669 # Known toolset versions, in order of preference.
1670 .known-versions = 14.1 14.0 12.0 11.0 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1
1671 7.1toolkit 7.0 6.0 ;
1674 .version-alias-6 = 6.0 ;
1675 .version-alias-6.5 = 6.0 ;
1676 .version-alias-7 = 7.0 ;
1677 .version-alias-8 = 8.0 ;
1678 .version-alias-9 = 9.0 ;
1679 .version-alias-10 = 10.0 ;
1680 .version-alias-11 = 11.0 ;
1681 .version-alias-12 = 12.0 ;
1682 .version-alias-14 = 14.0 ;
1683 .version-alias-14.1 = 14.1 ;
1685 # Names of registry keys containing the Visual C++ installation path (relative
1686 # to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
1687 .version-6.0-reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++" ;
1688 .version-7.0-reg = "VisualStudio\\7.0\\Setup\\VC" ;
1689 .version-7.1-reg = "VisualStudio\\7.1\\Setup\\VC" ;
1690 .version-8.0-reg = "VisualStudio\\8.0\\Setup\\VC" ;
1691 .version-8.0express-reg = "VCExpress\\8.0\\Setup\\VC" ;
1692 .version-9.0-reg = "VisualStudio\\9.0\\Setup\\VC" ;
1693 .version-9.0express-reg = "VCExpress\\9.0\\Setup\\VC" ;
1694 .version-10.0-reg = "VisualStudio\\10.0\\Setup\\VC" ;
1695 .version-10.0express-reg = "VCExpress\\10.0\\Setup\\VC" ;
1696 .version-11.0-reg = "VisualStudio\\11.0\\Setup\\VC" ;
1697 .version-12.0-reg = "VisualStudio\\12.0\\Setup\\VC" ;
1698 .version-14.0-reg = "VisualStudio\\14.0\\Setup\\VC" ;
1700 # Visual C++ Toolkit 2003 does not store its installation path in the registry.
1701 # The environment variable 'VCToolkitInstallDir' and the default installation
1702 # path will be checked instead.
1703 .version-7.1toolkit-path = "Microsoft Visual C++ Toolkit 2003/bin" ;
1704 .version-7.1toolkit-env = VCToolkitInstallDir ;
1705 # Visual Studio 2017 doesn't use a registry at all. And the suggested methods
1706 # of discovery involve having a compiled program. So as a fallback we search
1707 # paths for VS2017 (aka msvc >= 14.1).
1708 .version-14.1-path =
1709 "../../VC/Tools/MSVC/*/bin/Host*/*"
1710 "Microsoft Visual Studio/2017/*/VC/Tools/MSVC/*/bin/Host*/*"
1712 .version-14.1-env = VS150COMNTOOLS ProgramFiles ProgramFiles(x86) ;
1714 # Auto-detect all the available msvc installations on the system.
1715 auto-detect-toolset-versions ;
1718 # And finally trigger the actual Boost Build toolset registration.