# Copyright (c) 2003 David Abrahams # Copyright (c) 2005 Vladimir Prus # Copyright (c) 2005 Alexey Pakhunov # Copyright (c) 2006 Bojan Resnik # Copyright (c) 2006 Ilya Sokolov # Copyright (c) 2007 Rene Rivera # Copyright (c) 2008 Jurko Gospodnetic # Copyright (c) 2014 Microsoft Corporation # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) ################################################################################ # # MSVC Boost Build toolset module. # -------------------------------- # # All toolset versions need to have their location either auto-detected or # explicitly specified except for the special 'default' version that expects the # environment to find the needed tools or report an error. # ################################################################################ import "class" : new ; import common ; import feature ; import generators ; import mc ; import midl ; import os ; import path ; import pch ; import property ; import rc ; import set ; import toolset ; import type ; type.register MANIFEST : manifest ; feature.feature embed-manifest : on off : incidental propagated ; feature.feature embed-manifest-file : : free dependency ; type.register PDB : pdb ; ################################################################################ # # Public rules. # ################################################################################ # Initialize a specific toolset version configuration. As the result, path to # compiler and, possible, program names are set up, and will be used when that # version of compiler is requested. For example, you might have: # # using msvc : 6.5 : cl.exe ; # using msvc : 7.0 : Y:/foo/bar/cl.exe ; # # The version parameter may be omitted: # # using msvc : : Z:/foo/bar/cl.exe ; # # The following keywords have special meanings when specified as versions: # - all - all detected but not yet used versions will be marked as used # with their default options. # - default - this is an equivalent to an empty version. # # Depending on a supplied version, detected configurations and presence 'cl.exe' # in the path different results may be achieved. The following table describes # the possible scenarios: # # Nothing "x.y" # Passed Nothing "x.y" detected, detected, # version detected detected cl.exe in path cl.exe in path # # default Error Use "x.y" Create "default" Use "x.y" # all None Use all None Use all # x.y - Use "x.y" - Use "x.y" # a.b Error Error Create "a.b" Create "a.b" # # "x.y" - refers to a detected version; # "a.b" - refers to an undetected version. # # FIXME: Currently the command parameter and the property parameter # seem to overlap in duties. Remove this duplication. This seems to be related # to why someone started preparing to replace init with configure rules. # rule init ( # The msvc version being configured. When omitted the tools invoked when no # explicit version is given will be configured. version ? # The command used to invoke the compiler. If not specified: # - if version is given, default location for that version will be # searched # # - if version is not given, default locations for MSVC 9.0, 8.0, 7.1, 7.0 # and 6.* will be searched # # - if compiler is not found in the default locations, PATH will be # searched. : command * # Options may include: # # All options shared by multiple toolset types as handled by the # common.handle-options() rule, e.g. , , , # & . # # # # # # # # Exact tool names to be used by this msvc toolset configuration. # # # Command through which to pipe the output of running the compiler. # For example to pass the output to STLfilt. # # # Global setup command to invoke before running any of the msvc tools. # It will be passed additional option parameters depending on the actual # target platform. # # # # # # # # Platform specific setup command to invoke before running any of the # msvc tools used when builing a target for a specific platform, e.g. # when building a 32 or 64 bit executable. # # # Whether to rewrite setup scripts. New scripts will be output in # TEMP directory and will be used instead of originals in build actions. # Possible values: # * on - rewrite scripts, if they do not already exist (default) # * always - always rewrite scripts, even if they already exist # * off - use original setup scripts : options * ) { if $(command) { options += $(command) ; } configure $(version) : $(options) ; } # 'configure' is a newer version of 'init'. The parameter 'command' is passed as # a part of the 'options' list. See the 'init' rule comment for more detailed # information. # rule configure ( version ? : options * ) { switch $(version) { case "all" : if $(options) { import errors ; errors.error "MSVC toolset configuration: options should be" "empty when '$(version)' is specified." ; } # Configure (i.e. mark as used) all registered versions. local all-versions = [ $(.versions).all ] ; if ! $(all-versions) { if $(.debug-configuration) { ECHO "notice: [msvc-cfg] Asked to configure all registered" "msvc toolset versions when there are none currently" "registered." ; } } else { for local v in $(all-versions) { # Note that there is no need to skip already configured # versions here as this will request configure-really rule # to configure the version using default options which will # in turn cause it to simply do nothing in case the version # has already been configured. configure-really $(v) ; } } case "default" : configure-really : $(options) ; case * : configure-really $(version) : $(options) ; } } # Sets up flag definitions dependent on the compiler version used. # - 'version' is the version of compiler in N.M format. # - 'conditions' is the property set to be used as flag conditions. # - 'toolset' is the toolset for which flag settings are to be defined. # This makes the rule reusable for other msvc-option-compatible compilers. # rule configure-version-specific ( toolset : version : conditions ) { toolset.push-checking-for-flags-module unchecked ; # Starting with versions 7.0, the msvc compiler have the /Zc:forScope and # /Zc:wchar_t options that improve C++ standard conformance, but those # options are off by default. If we are sure that the msvc version is at # 7.*, add those options explicitly. We can be sure either if user specified # version 7.* explicitly or if we auto-detected the version ourselves. if ! [ MATCH ^(6\\.) : $(version) ] { toolset.flags $(toolset).compile CFLAGS $(conditions) : /Zc:forScope /Zc:wchar_t ; toolset.flags $(toolset).compile.c++ C++FLAGS $(conditions) : /wd4675 ; # Explicitly disable the 'function is deprecated' warning. Some msvc # versions have a bug, causing them to emit the deprecation warning even # with /W0. toolset.flags $(toolset).compile CFLAGS $(conditions)/off : /wd4996 ; if [ MATCH ^([78]\\.) : $(version) ] { # 64-bit compatibility warning deprecated since 9.0, see # http://msdn.microsoft.com/en-us/library/yt4xw8fh.aspx toolset.flags $(toolset).compile CFLAGS $(conditions)/all : /Wp64 ; } } # # Processor-specific optimization. # if [ MATCH ^([67]) : $(version) ] { # 8.0 deprecates some of the options. toolset.flags $(toolset).compile CFLAGS $(conditions)/speed $(conditions)/space : /Ogiy /Gs ; toolset.flags $(toolset).compile CFLAGS $(conditions)/speed : /Ot ; toolset.flags $(toolset).compile CFLAGS $(conditions)/space : /Os ; toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/ : /GB ; toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/i486 : /G4 ; toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/$(.cpu-type-g5) : /G5 ; toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/$(.cpu-type-g6) : /G6 ; toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/$(.cpu-type-g7) : /G7 ; # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math" # tests will fail. toolset.flags $(toolset).compile CFLAGS $(conditions) : /Op ; # 7.1 and below have single-threaded static RTL. toolset.flags $(toolset).compile CFLAGS $(conditions)/off/static/single : /ML ; toolset.flags $(toolset).compile CFLAGS $(conditions)/on/static/single : /MLd ; } else { # 8.0 and above adds some more options. toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/ : /favor:blend ; toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/$(.cpu-type-em64t) : /favor:EM64T ; toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/$(.cpu-type-amd64) : /favor:AMD64 ; # 8.0 and above only has multi-threaded static RTL. toolset.flags $(toolset).compile CFLAGS $(conditions)/off/static/single : /MT ; toolset.flags $(toolset).compile CFLAGS $(conditions)/on/static/single : /MTd ; # Specify target machine type so the linker will not need to guess. toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-amd64) : /MACHINE:X64 ; toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-i386) : /MACHINE:X86 ; toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-ia64) : /MACHINE:IA64 ; toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-arm) : /MACHINE:ARM ; # Make sure that manifest will be generated even if there is no # dependencies to put there. toolset.flags $(toolset).link LINKFLAGS $(conditions) : /MANIFEST ; } # Starting with Visual Studio 2013 the CRT is split into a desktop and app dll. #If targeting WinRT and 12.0 set lib path to link against app CRT. if [ MATCH "(12)" : $(version) ] { local VCPath = [ path.parent [ path.make [ default-path $(version) ] ] ] ; local storeLibPath = [ path.join [ path.join $(VCPath) "lib" ] "store" ] ; toolset.flags $(toolset).link LINKPATH $(conditions)/store/$(.cpu-arch-i386) : [ path.native $(storeLibPath) ] ; toolset.flags $(toolset).link LINKPATH $(conditions)/store/$(.cpu-arch-amd64) : [ path.native [ path.join $(storeLibPath) "amd64" ] ] ; toolset.flags $(toolset).link LINKPATH $(conditions)/store/$(.cpu-arch-arm) : [ path.native [ path.join $(storeLibPath) "arm" ] ] ; } toolset.pop-checking-for-flags-module ; } # Feature for handling targeting different Windows API sets. feature.feature windows-api : desktop store phone : propagated composite link-incompatible ; feature.compose store : WINAPI_FAMILY=WINAPI_FAMILY_APP _WIN32_WINNT=0x0602 /APPCONTAINER ; feature.compose phone : WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP _WIN32_WINNT=0x0602 /APPCONTAINER /NODEFAULTLIB:ole32.lib /NODEFAULTLIB:kernel32.lib WindowsPhoneCore.lib ; feature.set-default windows-api : desktop ; # Registers this toolset including all of its flags, features & generators. Does # nothing on repeated calls. # rule register-toolset ( ) { if ! msvc in [ feature.values toolset ] { register-toolset-really ; } } rule resolve-possible-msvc-version-alias ( version ) { if $(.version-alias-$(version)) { version = $(.version-alias-$(version)) ; } return $(version) ; } # Declare action for creating static libraries. If library exists, remove it # before adding files. See # http://article.gmane.org/gmane.comp.lib.boost.build/4241 for rationale. if [ os.name ] in NT { # The 'DEL' command would issue a message to stdout if the file does not # exist, so need a check. actions archive { if exist "$(<[1])" DEL "$(<[1])" $(.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")" } } else { actions archive { $(.RM) "$(<[1])" $(.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")" } } # For the assembler the following options are turned on by default: # # -Zp4 align structures to 4 bytes # -Cp preserve case of user identifiers # -Cx preserve case in publics, externs # actions compile.asm { $(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)" } rule compile.c ( targets + : sources * : properties * ) { C++FLAGS on $(targets[1]) = ; get-rspline $(targets) : -TC ; compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } rule compile.c.preprocess ( targets + : sources * : properties * ) { C++FLAGS on $(targets[1]) = ; get-rspline $(targets) : -TC ; preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } rule compile.c.pch ( targets + : sources * : properties * ) { C++FLAGS on $(targets[1]) = ; get-rspline $(targets[1]) : -TC ; get-rspline $(targets[2]) : -TC ; local pch-source = [ on $(<) return $(PCH_SOURCE) ] ; if $(pch-source) { DEPENDS $(<) : $(pch-source) ; compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ; } else { compile-c-c++-pch $(targets) : $(sources) ; } } toolset.flags msvc YLOPTION : "-Yl" ; # Action for running the C/C++ compiler without using precompiled headers. # # WARNING: Synchronize any changes this in action with intel-win # # Notes regarding PDB generation, for when we use # on/database: # # 1. PDB_CFLAG is only set for on/database, ensuring # that the /Fd flag is dropped if PDB_CFLAG is empty. # # 2. When compiling executables's source files, PDB_NAME is set on a per-source # file basis by rule compile-c-c++. The linker will pull these into the # executable's PDB. # # 3. When compiling library's source files, PDB_NAME is updated to .pdb # for each source file by rule archive, as in this case compiler must be used # to create a single PDB for our library. # actions compile-c-c++ bind PDB_NAME { $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER) } actions preprocess-c-c++ bind PDB_NAME { $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)" } rule compile-c-c++ ( targets + : sources * ) { DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ; DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ; PDB_NAME on $(<) = $(<[1]:S=.pdb) ; LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ; } rule preprocess-c-c++ ( targets + : sources * ) { DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ; DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ; PDB_NAME on $(<) = $(<:S=.pdb) ; LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ; } # Action for running the C/C++ compiler using precompiled headers. In addition # to whatever else it needs to compile, this action also adds a temporary source # .cpp file used to compile the precompiled headers themselves. # # The global .escaped-double-quote variable is used to avoid messing up Emacs # syntax highlighting in the messy N-quoted code below. actions compile-c-c++-pch { $(.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) } # Action for running the C/C++ compiler using precompiled headers. An already # built source file for compiling the precompiled headers is expected to be # given as one of the source parameters. actions compile-c-c++-pch-s { $(.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) } rule compile.c++ ( targets + : sources * : properties * ) { get-rspline $(targets) : -TP ; compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } rule compile.c++.preprocess ( targets + : sources * : properties * ) { get-rspline $(targets) : -TP ; preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } rule compile.c++.pch ( targets + : sources * : properties * ) { get-rspline $(targets[1]) : -TP ; get-rspline $(targets[2]) : -TP ; local pch-source = [ on $(<) return $(PCH_SOURCE) ] ; if $(pch-source) { DEPENDS $(<) : $(pch-source) ; compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ; } else { compile-c-c++-pch $(targets) : $(sources) ; } } # See midl.jam for details. # actions compile.idl { $(.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)")" $(.TOUCH_FILE) "$(<[4]:W)" $(.TOUCH_FILE) "$(<[5]:W)" } actions compile.mc { $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)" } actions compile.rc { $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)" } rule link ( targets + : sources * : properties * ) { if on in $(properties) { if [ feature.get-values : $(properties) ] { DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ; msvc.manifest.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ; } else { msvc.manifest $(targets) : $(sources) : $(properties) ; } } } rule link.dll ( targets + : sources * : properties * ) { DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ; if on in $(properties) { if [ feature.get-values : $(properties) ] { DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ; msvc.manifest.dll.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ; } else { msvc.manifest.dll $(targets) : $(sources) : $(properties) ; } } } # Incremental linking a DLL causes no end of problems: if the actual exports do # not change, the import .lib file is never updated. Therefore, the .lib is # always out-of-date and gets rebuilt every time. I am not sure that incremental # linking is such a great idea in general, but in this case I am sure we do not # want it. # Windows manifest is a new way to specify dependencies on managed DotNet # assemblies and Windows native DLLs. The manifests are embedded as resources # and are useful in any PE target (both DLL and EXE). if [ os.name ] in NT { actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE { $(.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")" if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% } actions manifest { if exist "$(<[1]).manifest" ( $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1" ) } actions manifest.user bind EMBED_MANIFEST_FILE { $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);1" } actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE { $(.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")" if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% } actions manifest.dll { if exist "$(<[1]).manifest" ( $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2" ) } actions manifest.dll.user bind EMBED_MANIFEST_FILE { $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2" } } else { actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE { $(.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")" } actions manifest { if test -e "$(<[1]).manifest"; then $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);1" fi } actions link.dll bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE { $(.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")" } actions manifest.dll { if test -e "$(<[1]).manifest"; then $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2" fi } actions manifest.dll.user bind EMBED_MANIFEST_FILE { $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2" } } # This rule sets up the pdb file that will be used when generating static # libraries and the debug-store option is database, so that the compiler puts # all the debug info into a single .pdb file named after the library. # # Poking at source targets this way is probably not clean, but it is the # easiest approach. # rule archive ( targets + : sources * : properties * ) { PDB_NAME on $(>) = $(<[1]:S=.pdb) ; LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ; } ################################################################################ # # Classes. # ################################################################################ class msvc-pch-generator : pch-generator { import property-set ; rule run-pch ( project name ? : property-set : sources * ) { # Searching for the header and source file in the sources. local pch-header ; local pch-source ; for local s in $(sources) { if [ type.is-derived [ $(s).type ] H ] { pch-header = $(s) ; } else if [ type.is-derived [ $(s).type ] CPP ] || [ type.is-derived [ $(s).type ] C ] { pch-source = $(s) ; } } if ! $(pch-header) { import errors : user-error : errors.user-error ; errors.user-error "can not build pch without pch-header" ; } # If we do not have the PCH source - that is fine. We will just create a # temporary .cpp file in the action. local generated = [ generator.run $(project) $(name) : [ property-set.create # Passing of is a dirty trick, needed because # non-composing generators with multiple inputs are subtly # broken. For more detailed information see: # https://zigzag.cs.msu.su:7813/boost.build/ticket/111 $(pch-source) [ $(property-set).raw ] ] : $(pch-header) ] ; local pch-file ; for local g in $(generated) { if [ type.is-derived [ $(g).type ] PCH ] { pch-file = $(g) ; } } return [ property-set.create $(pch-header) $(pch-file) ] $(generated) ; } } ################################################################################ # # Local rules. # ################################################################################ # Detects versions listed as '.known-versions' by checking registry information, # environment variables & default paths. Supports both native Windows and # Cygwin. # local rule auto-detect-toolset-versions ( ) { if [ os.name ] in NT CYGWIN { # Get installation paths from the registry. for local i in $(.known-versions) { if $(.version-$(i)-reg) { local vc-path ; for local x in "" "Wow6432Node\\" { vc-path += [ W32_GETREG "HKEY_LOCAL_MACHINE\\SOFTWARE\\"$(x)"\\Microsoft\\"$(.version-$(i)-reg) : "ProductDir" ] ; } if $(vc-path) { vc-path = [ path.join [ path.make-NT $(vc-path[1]) ] "bin" ] ; register-configuration $(i) : [ path.native $(vc-path[1]) ] ; } } } } # Check environment and default installation paths. for local i in $(.known-versions) { if ! $(i) in [ $(.versions).all ] { register-configuration $(i) : [ default-path $(i) ] ; } } } # Helper rule to generate a faster alternative to MSVC setup scripts. # We used to call MSVC setup scripts directly in every action, however in # newer MSVC versions (10.0+) they make long-lasting registry queries # which have a significant impact on build time. rule maybe-rewrite-setup ( toolset : setup-script : setup-options : version : rewrite-setup ? ) { local result = $(setup-script)" "$(setup-options) ; # At the moment we only know how to rewrite scripts with cmd shell. if ( [ os.name ] in NT ) && ( $(rewrite-setup) != off ) { setup-script-id = b2_$(toolset)_$(version)_$(setup-script:B) ; if $(setup-options)-is-not-empty { setup-script-id = $(setup-script-id)_$(setup-options) ; } if $(.$(setup-script-id)) { errors.error rewriting setup script for the second time ; } local tmpdir = [ os.environ TEMP ] ; local replacement = [ path.native $(tmpdir)/$(setup-script-id).cmd ] ; if ( $(rewrite-setup) = always ) || ( ! [ path.exists $(replacement) ] ) { local original-vars = [ SPLIT_BY_CHARACTERS [ SHELL set ] : "\n" ] ; local new-vars = [ SPLIT_BY_CHARACTERS [ SHELL "$(setup-script) $(setup-options)>nul && set" ] : "\n" ] ; local diff-vars = [ set.difference $(new-vars) : $(original-vars) ] ; if $(diff-vars) { local target = $(replacement) ; FILE_CONTENTS on $(target) = "SET "$(diff-vars) ; ALWAYS $(target) ; msvc.write-setup-script $(target) ; UPDATE_NOW $(target) : : ignore-minus-n ; .$(setup-script-id) = $(replacement) ; result = "\""$(replacement)"\"" ; } } else { result = "\""$(replacement)"\"" ; } } return $(result) ; } actions write-setup-script { @($(STDOUT):E=$(FILE_CONTENTS:J=$(.nl))) > "$(<)" } # Local helper rule to create the vcvars setup command for given architecture # and options. # local rule generate-setup-cmd ( version : command : parent : options * : cpu : global-setup : default-global-setup-options : default-setup ) { local setup-prefix = "call " ; local setup-suffix = " >nul"$(.nl) ; if ! [ os.name ] in NT { setup-prefix = "cmd.exe /S /C call " ; setup-suffix = " \">nul\" \"&&\" " ; } local setup-options ; local setup = [ feature.get-values : $(options) ] ; if ! $(setup)-is-defined { if $(global-setup)-is-defined { setup = $(global-setup) ; # If needed we can easily add using configuration flags # here for overriding which options get passed to the # global setup command for which target platform: # setup-options = [ feature.get-values : $(options) ] ; setup-options ?= $(default-global-setup-options) ; } else { setup = [ locate-default-setup $(command) : $(parent) : $(default-setup) ] ; } } # Cygwin to Windows path translation. setup = "\""$(setup:W)"\"" ; # Append setup options to the setup name and add the final setup # prefix & suffix. setup-options ?= "" ; local rewrite = [ feature.get-values : $(options) ] ; setup = [ maybe-rewrite-setup msvc : $(setup:J=" ") : $(setup-options:J=" ") : $(version) : $(rewrite) ] ; setup = $(setup-prefix)$(setup)$(setup-suffix) ; return $(setup) ; } # Worker rule for toolset version configuration. Takes an explicit version id or # nothing in case it should configure the default toolset version (the first # registered one or a new 'default' one in case no toolset versions have been # registered yet). # local rule configure-really ( version ? : options * ) { local v = $(version) ; # Decide what the 'default' version is. if ! $(v) { # Take the first registered (i.e. auto-detected) version. version = [ $(.versions).all ] ; version = $(version[1]) ; v = $(version) ; # Note: 'version' can still be empty at this point if no versions have # been auto-detected. version ?= "default" ; } # Version alias -> real version number. version = [ resolve-possible-msvc-version-alias $(version) ] ; # Check whether the selected configuration is already in use. if $(version) in [ $(.versions).used ] { # Allow multiple 'toolset.using' calls for the same configuration if the # identical sets of options are used. if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] ) { import errors ; errors.error "MSVC toolset configuration: Toolset version" "'$(version)' already configured." ; } } else { # Register a new configuration. $(.versions).register $(version) ; # Add user-supplied to auto-detected options. options = [ $(.versions).get $(version) : options ] $(options) ; # Mark the configuration as 'used'. $(.versions).use $(version) ; # Generate conditions and save them. local conditions = [ common.check-init-parameters msvc : version $(v) ] ; $(.versions).set $(version) : conditions : $(conditions) ; local command = [ feature.get-values : $(options) ] ; # If version is specified, we try to search first in default paths, and # only then in PATH. command = [ common.get-invocation-command msvc : cl.exe : $(command) : [ default-paths $(version) ] : $(version) ] ; common.handle-options msvc : $(conditions) : $(command) : $(options) ; if ! $(version) { # Even if version is not explicitly specified, try to detect the # version from the path. # FIXME: We currently detect both Microsoft Visual Studio 9.0 and # 9.0express as 9.0 here. if [ MATCH "(Microsoft Visual Studio 14)" : $(command) ] { version = 14.0 ; } else if [ MATCH "(Microsoft Visual Studio 12)" : $(command) ] { version = 12.0 ; } else if [ MATCH "(Microsoft Visual Studio 11)" : $(command) ] { version = 11.0 ; } else if [ MATCH "(Microsoft Visual Studio 10)" : $(command) ] { version = 10.0 ; } else if [ MATCH "(Microsoft Visual Studio 9)" : $(command) ] { version = 9.0 ; } else if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ] { version = 8.0 ; } else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ] { version = 7.1 ; } else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" : $(command) ] { version = 7.1toolkit ; } else if [ MATCH "(.NET[\/\\]VC7)" : $(command) ] { version = 7.0 ; } else { version = 6.0 ; } } # Generate and register setup command. local below-8.0 = [ MATCH ^([67]\\.) : $(version) ] ; local below-11.0 = [ MATCH ^([6789]\\.|10\\.) : $(version) ] ; local cpu = i386 amd64 ia64 arm ; if $(below-8.0) { cpu = i386 ; } if $(below-11.0) { cpu = i386 amd64 ia64 ; } local setup-amd64 ; local setup-i386 ; local setup-ia64 ; local setup-arm ; local setup-phone-i386 ; local setup-phone-arm ; if $(command) { # TODO: Note that if we specify a non-existant toolset version then # this rule may find and use a corresponding compiler executable # belonging to an incorrect toolset version. For example, if you # have only MSVC 7.1 installed, have its executable on the path and # specify you want Boost Build to use MSVC 9.0, then you want Boost # Build to report an error but this may cause it to silently use the # MSVC 7.1 compiler even though it thinks it is using the msvc-9.0 # toolset version. command = [ common.get-absolute-tool-path $(command[-1]) ] ; } if $(command) { local parent = [ path.make $(command) ] ; parent = [ path.parent $(parent) ] ; parent = [ path.native $(parent) ] ; # Setup will be used if the command name has been specified. If # setup is not specified explicitly then a default setup script will # be used instead. Setup scripts may be global or architecture/ # /platform/cpu specific. Setup options are used only in case of # global setup scripts. # Default setup scripts provided with different VC distributions: # # VC 7.1 had only the vcvars32.bat script specific to 32 bit i386 # builds. It was located in the bin folder for the regular version # and in the root folder for the free VC 7.1 tools. # # Later 8.0 & 9.0 versions introduce separate platform specific # vcvars*.bat scripts (e.g. 32 bit, 64 bit AMD or 64 bit Itanium) # located in or under the bin folder. Most also include a global # vcvarsall.bat helper script located in the root folder which runs # one of the aforementioned vcvars*.bat scripts based on the options # passed to it. So far only the version coming with some PlatformSDK # distributions does not include this top level script but to # support those we need to fall back to using the worker scripts # directly in case the top level script can not be found. local global-setup = [ feature.get-values : $(options) ] ; global-setup = $(global-setup[1]) ; local global-setup-phone = $(global-setup) ; if ! $(below-8.0) { global-setup ?= [ locate-default-setup $(command) : $(parent) : vcvarsall.bat ] ; } local default-setup-amd64 = vcvarsx86_amd64.bat ; local default-setup-i386 = vcvars32.bat ; local default-setup-ia64 = vcvarsx86_ia64.bat ; local default-setup-arm = vcvarsx86_arm.bat ; local default-setup-phone-i386 = vcvarsphonex86.bat ; local default-setup-phone-arm = vcvarsphonex86_arm.bat ; # http://msdn2.microsoft.com/en-us/library/x4d2c09s(VS.80).aspx and # http://msdn2.microsoft.com/en-us/library/x4d2c09s(vs.90).aspx # mention an x86_IPF option, that seems to be a documentation bug # and x86_ia64 is the correct option. local default-global-setup-options-amd64 = x86_amd64 ; local default-global-setup-options-i386 = x86 ; local default-global-setup-options-ia64 = x86_ia64 ; local default-global-setup-options-arm = x86_arm ; # When using 64-bit Windows, and targeting 64-bit, it is possible to # use a native 64-bit compiler, selected by the "amd64" & "ia64" # parameters to vcvarsall.bat. There are two variables we can use -- # PROCESSOR_ARCHITECTURE and PROCESSOR_IDENTIFIER. The first is # 'x86' when running 32-bit Windows, no matter which processor is # used, and 'AMD64' on 64-bit windows on x86 (either AMD64 or EM64T) # Windows. # if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITECTURE ] ] { default-global-setup-options-amd64 = amd64 ; } # TODO: The same 'native compiler usage' should be implemented for # the Itanium platform by using the "ia64" parameter. For this # though we need someone with access to this platform who can find # out how to correctly detect this case. else if $(somehow-detect-the-itanium-platform) { default-global-setup-options-ia64 = ia64 ; } for local c in $(cpu) { setup-$(c) = [ generate-setup-cmd $(version) : $(command) : $(parent) : $(options) : $(c) : $(global-setup) : $(default-global-setup-options-$(c)) : $(default-setup-$(c)) ] ; } # Windows phone has different setup scripts, located in a different directory hierarchy. # The 11.0 toolset can target Windows Phone 8.0 and the 12.0 toolset can target Windows Phone 8.1, # each of which have a different directory for their vcvars setup scripts. local phone-parent = [ path.native [ path.join $(parent) WPSDK ] ] ; local phone-directory = $(phone-parent) ; if [ MATCH "(11.0)" : $(version) ] { phone-directory = [ path.native [ path.join $(phone-directory) WP80 ] ] ; } else if [ MATCH "(12.0)" : $(version) ] { phone-directory = [ path.native [ path.join $(phone-directory) WP81 ] ] ; } global-setup-phone ?= [ locate-default-setup $(phone-directory) : $(phone-parent) : vcvarsphoneall.bat ] ; # If can't locate default phone setup script then this VS version doesn't support Windows Phone. if $(global-setup-phone)-is-defined { # i386 CPU is for the Windows Phone emulator in Visual Studio. local phone-cpu = i386 arm ; for local c in $(phone-cpu) { 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)) ] ; } } } # Get tool names (if any) and finish setup. compiler = [ feature.get-values : $(options) ] ; compiler ?= cl ; linker = [ feature.get-values : $(options) ] ; linker ?= link ; resource-compiler = [ feature.get-values : $(options) ] ; resource-compiler ?= rc ; # Turn on some options for i386 assembler # -coff generate COFF format object file (compatible with cl.exe output) local default-assembler-amd64 = ml64 ; local default-assembler-i386 = "ml -coff" ; local default-assembler-ia64 = ias ; local default-assembler-ia64 = armasm ; assembler = [ feature.get-values : $(options) ] ; idl-compiler = [ feature.get-values : $(options) ] ; idl-compiler ?= midl ; mc-compiler = [ feature.get-values : $(options) ] ; mc-compiler ?= mc ; manifest-tool = [ feature.get-values : $(options) ] ; manifest-tool ?= mt ; local cc-filter = [ feature.get-values : $(options) ] ; for local c in $(cpu) { # Setup script is not required in some configurations. setup-$(c) ?= "" ; local cpu-conditions = $(conditions)/$(.cpu-arch-$(c)) ; if $(.debug-configuration) { for local cpu-condition in $(cpu-conditions) { ECHO "notice: [msvc-cfg] condition: '$(cpu-condition)', setup: '$(setup-$(c))'" ; } } local cpu-assembler = $(assembler) ; cpu-assembler ?= $(default-assembler-$(c)) ; toolset.flags msvc.compile .RC $(api)/$(cpu-conditions) : $(setup-$(c))$(resource-compiler) ; toolset.flags msvc.compile .IDL $(api)/$(cpu-conditions) : $(setup-$(c))$(idl-compiler) ; toolset.flags msvc.compile .MC $(api)/$(cpu-conditions) : $(setup-$(c))$(mc-compiler) ; toolset.flags msvc.link .MT $(api)/$(cpu-conditions) : $(setup-$(c))$(manifest-tool) -nologo ; for api in desktop store phone { local setup-script = $(setup-$(c)) ; if $(api) = phone { setup-script = $(setup-phone-$(c)) ; } toolset.flags msvc.compile .CC $(api)/$(cpu-conditions) : $(setup-script)$(compiler) /Zm800 -nologo ; toolset.flags msvc.compile .ASM $(api)/$(cpu-conditions) : $(setup-script)$(cpu-assembler) -nologo ; toolset.flags msvc.link .LD $(api)/$(cpu-conditions) : $(setup-script)$(linker) /NOLOGO /INCREMENTAL:NO ; toolset.flags msvc.archive .LD $(api)/$(cpu-conditions) : $(setup-script)$(linker) /lib /NOLOGO ; } if $(cc-filter) { toolset.flags msvc .CC.FILTER $(cpu-conditions) : "|" $(cc-filter) ; } } # Set version-specific flags. configure-version-specific msvc : $(version) : $(conditions) ; } } # Returns the default installation path for the given version. # local rule default-path ( version ) { # Use auto-detected path if possible. local path = [ feature.get-values : [ $(.versions).get $(version) : options ] ] ; if $(path) { path = $(path:D) ; } else { # Check environment. if $(.version-$(version)-env) { local vc-path = [ os.environ $(.version-$(version)-env) ] ; if $(vc-path) { vc-path = [ path.make $(vc-path) ] ; vc-path = [ path.join $(vc-path) $(.version-$(version)-envpath) ] ; vc-path = [ path.native $(vc-path) ] ; path = $(vc-path) ; } } # Check default path. if ! $(path) && $(.version-$(version)-path) { path = [ path.native [ path.join $(.ProgramFiles) $(.version-$(version)-path) ] ] ; } } return $(path) ; } # Returns either the default installation path (if 'version' is not empty) or # list of all known default paths (if no version is given) # local rule default-paths ( version ? ) { local possible-paths ; if $(version) { possible-paths += [ default-path $(version) ] ; } else { for local i in $(.known-versions) { possible-paths += [ default-path $(i) ] ; } } return $(possible-paths) ; } rule get-rspline ( target : lang-opt ) { CC_RSPLINE on $(target) = [ on $(target) return $(lang-opt) -U$(UNDEFS) $(CFLAGS) $(C++FLAGS) $(OPTIONS) -c $(.nl)-D$(DEFINES) $(.nl)\"-I$(INCLUDES:W)\" ] ; } class msvc-linking-generator : linking-generator { # Calls the base version. If necessary, also create a target for the # manifest file.specifying source's name as the name of the created # target. As result, the PCH will be named whatever.hpp.gch, and not # whatever.gch. rule generated-targets ( sources + : property-set : project name ? ) { local result = [ linking-generator.generated-targets $(sources) : $(property-set) : $(project) $(name) ] ; if $(result) { local name-main = [ $(result[0]).name ] ; local action = [ $(result[0]).action ] ; if [ $(property-set).get ] = "on" { # We force the exact name on PDB. The reason is tagging -- the # tag rule may reasonably special case some target types, like # SHARED_LIB. The tag rule will not catch PDBs, and it cannot # even easily figure out if a PDB is paired with a SHARED_LIB, # EXE or something else. Because PDBs always get the same name # as the main target, with .pdb as extension, just force it. local target = [ class.new file-target $(name-main:S=.pdb) exact : PDB : $(project) : $(action) ] ; local registered-target = [ virtual-target.register $(target) ] ; if $(target) != $(registered-target) { $(action).replace-targets $(target) : $(registered-target) ; } result += $(registered-target) ; } if [ $(property-set).get ] = "off" { # Manifest is an evil target. It has .manifest appened to the # name of the main target, including extension, e.g. # a.exe.manifest. We use the 'exact' name to achieve this # effect. local target = [ class.new file-target $(name-main).manifest exact : MANIFEST : $(project) : $(action) ] ; local registered-target = [ virtual-target.register $(target) ] ; if $(target) != $(registered-target) { $(action).replace-targets $(target) : $(registered-target) ; } result += $(registered-target) ; } } return $(result) ; } } # Unsafe worker rule for the register-toolset() rule. Must not be called # multiple times. # local rule register-toolset-really ( ) { feature.extend toolset : msvc ; # Intel and msvc supposedly have link-compatible objects. feature.subfeature toolset msvc : vendor : intel : propagated optional ; # Inherit MIDL flags. toolset.inherit-flags msvc : midl ; # Inherit MC flags. toolset.inherit-flags msvc : mc ; # Dynamic runtime comes only in MT flavour. toolset.add-requirements msvc,shared:multi ; # Declare msvc toolset specific features. { feature.feature debug-store : object database : propagated ; feature.feature pch-source : : dependency free ; } # Declare generators. { # TODO: Is it possible to combine these? Make the generators # non-composing so that they do not convert each source into a separate # .rsp file. generators.register [ new msvc-linking-generator msvc.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : msvc ] ; generators.register [ new msvc-linking-generator msvc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB : msvc false ] ; generators.register [ new msvc-linking-generator msvc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB : msvc true ] ; generators.register-archiver msvc.archive : OBJ : STATIC_LIB : msvc ; generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : msvc ; generators.register-c-compiler msvc.compile.c : C : OBJ : msvc ; generators.register-c-compiler msvc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : msvc ; generators.register-c-compiler msvc.compile.c.preprocess : C : PREPROCESSED_C : msvc ; # Using 'register-c-compiler' adds the build directory to INCLUDES. generators.register-c-compiler msvc.compile.rc : RC : OBJ(%_res) : msvc ; generators.override msvc.compile.rc : rc.compile.resource ; generators.register-standard msvc.compile.asm : ASM : OBJ : msvc ; generators.register-c-compiler msvc.compile.idl : IDL : MSTYPELIB H C(%_i) C(%_proxy) C(%_dlldata) : msvc ; generators.override msvc.compile.idl : midl.compile.idl ; generators.register-standard msvc.compile.mc : MC : H RC : msvc ; generators.override msvc.compile.mc : mc.compile ; # Note: the 'H' source type will catch both '.h' and '.hpp' headers as # the latter have their HPP type derived from H. The type of compilation # is determined entirely by the destination type. generators.register [ new msvc-pch-generator msvc.compile.c.pch : H : C_PCH OBJ : on msvc ] ; generators.register [ new msvc-pch-generator msvc.compile.c++.pch : H : CPP_PCH OBJ : on msvc ] ; generators.override msvc.compile.c.pch : pch.default-c-pch-generator ; generators.override msvc.compile.c++.pch : pch.default-cpp-pch-generator ; } toolset.flags msvc.compile PCH_FILE on : ; toolset.flags msvc.compile PCH_SOURCE on : ; toolset.flags msvc.compile PCH_HEADER on : ; # # Declare flags for compilation. # toolset.flags msvc.compile CFLAGS speed : /O2 ; toolset.flags msvc.compile CFLAGS space : /O1 ; toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/$(.cpu-type-itanium) : /G1 ; toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/$(.cpu-type-itanium2) : /G2 ; toolset.flags msvc.compile CFLAGS on/object : /Z7 ; toolset.flags msvc.compile CFLAGS on/database : /Zi ; toolset.flags msvc.compile CFLAGS off : /Od ; toolset.flags msvc.compile CFLAGS off : /Ob0 ; toolset.flags msvc.compile CFLAGS on : /Ob1 ; toolset.flags msvc.compile CFLAGS full : /Ob2 ; toolset.flags msvc.compile CFLAGS on : /W3 ; toolset.flags msvc.compile CFLAGS off : /W0 ; toolset.flags msvc.compile CFLAGS all : /W4 ; toolset.flags msvc.compile CFLAGS on : /WX ; toolset.flags msvc.compile C++FLAGS on/off/off : /EHs ; toolset.flags msvc.compile C++FLAGS on/off/on : /EHsc ; toolset.flags msvc.compile C++FLAGS on/on/off : /EHa ; toolset.flags msvc.compile C++FLAGS on/on/on : /EHac ; # By default 8.0 enables rtti support while prior versions disabled it. We # simply enable or disable it explicitly so we do not have to depend on this # default behaviour. toolset.flags msvc.compile CFLAGS on : /GR ; toolset.flags msvc.compile CFLAGS off : /GR- ; toolset.flags msvc.compile CFLAGS off/shared : /MD ; toolset.flags msvc.compile CFLAGS on/shared : /MDd ; toolset.flags msvc.compile CFLAGS off/static/multi : /MT ; toolset.flags msvc.compile CFLAGS on/static/multi : /MTd ; toolset.flags msvc.compile OPTIONS : ; toolset.flags msvc.compile.c++ OPTIONS : ; toolset.flags msvc.compile PDB_CFLAG on/database : /Fd ; toolset.flags msvc.compile DEFINES ; toolset.flags msvc.compile UNDEFS ; toolset.flags msvc.compile INCLUDES ; # Declare flags for the assembler. toolset.flags msvc.compile.asm USER_ASMFLAGS ; toolset.flags msvc.compile.asm ASMFLAGS on : "/Zi /Zd" ; toolset.flags msvc.compile.asm ASMFLAGS on : /W3 ; toolset.flags msvc.compile.asm ASMFLAGS off : /W0 ; toolset.flags msvc.compile.asm ASMFLAGS all : /W4 ; toolset.flags msvc.compile.asm ASMFLAGS on : /WX ; toolset.flags msvc.compile.asm DEFINES ; # Declare flags for linking. { toolset.flags msvc.link PDB_LINKFLAG on/database : /PDB: ; # not used yet toolset.flags msvc.link LINKFLAGS on : /DEBUG ; toolset.flags msvc.link DEF_FILE ; # The linker disables the default optimizations when using /DEBUG so we # have to enable them manually for release builds with debug symbols. toolset.flags msvc LINKFLAGS on/off : /OPT:REF,ICF ; toolset.flags msvc LINKFLAGS console : /subsystem:console ; toolset.flags msvc LINKFLAGS gui : /subsystem:windows ; toolset.flags msvc LINKFLAGS wince : /subsystem:windowsce ; toolset.flags msvc LINKFLAGS native : /subsystem:native ; toolset.flags msvc LINKFLAGS auto : /subsystem:posix ; toolset.flags msvc.link OPTIONS ; toolset.flags msvc.link LINKPATH ; toolset.flags msvc.link FINDLIBS_ST ; toolset.flags msvc.link FINDLIBS_SA ; toolset.flags msvc.link LIBRARY_OPTION msvc : "" : unchecked ; toolset.flags msvc.link LIBRARIES_MENTIONED_BY_FILE : ; toolset.flags msvc.link.dll LINKFLAGS true : /NOENTRY ; } toolset.flags msvc.archive AROPTIONS ; } # Locates the requested setup script under the given folder and returns its full # path or nothing in case the script can not be found. In case multiple scripts # are found only the first one is returned. # # TODO: There used to exist a code comment for the msvc.init rule stating that # we do not correctly detect the location of the vcvars32.bat setup script for # the free VC7.1 tools in case user explicitly provides a path. This should be # tested or simply remove this whole comment in case this toolset version is no # longer important. # local rule locate-default-setup ( command : parent : setup-name ) { local result = [ GLOB $(command) $(parent) : $(setup-name) ] ; if $(result[1]) { return $(result[1]) ; } } # Validates given path, registers found configuration and prints debug # information about it. # local rule register-configuration ( version : path ? ) { if $(path) { local command = [ GLOB $(path) : cl.exe ] ; if $(command) { if $(.debug-configuration) { ECHO notice: [msvc-cfg] msvc-$(version) detected, command: '$(command)' ; } $(.versions).register $(version) ; $(.versions).set $(version) : options : $(command) ; } } } ################################################################################ # # Startup code executed when loading this module. # ################################################################################ if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] { .debug-configuration = true ; } # Miscellaneous constants. .RM = [ common.rm-command ] ; .nl = " " ; .ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ; .escaped-double-quote = "\"" ; .TOUCH_FILE = [ common.file-touch-command ] ; # List of all registered configurations. .versions = [ new configurations ] ; # Supported CPU architectures. .cpu-arch-i386 = / /32 x86/ x86/32 ; .cpu-arch-amd64 = /64 x86/64 ; .cpu-arch-ia64 = ia64/ ia64/64 ; .cpu-arch-arm = arm/ arm/32 ; # Supported CPU types (only Itanium optimization options are supported from # VC++ 2005 on). See # http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx for more # detailed information. .cpu-type-g5 = i586 pentium pentium-mmx ; .cpu-type-g6 = i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6 k6-2 k6-3 winchip-c6 winchip2 c3 c3-2 ; .cpu-type-em64t = prescott nocona core2 corei7 corei7-avx core-avx-i conroe conroe-xe conroe-l allendale merom merom-xe kentsfield kentsfield-xe penryn wolfdale yorksfield nehalem sandy-bridge ivy-bridge haswell ; .cpu-type-amd64 = k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3 athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3 btver1 btver2 ; .cpu-type-g7 = pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp athlon-mp $(.cpu-type-em64t) $(.cpu-type-amd64) ; .cpu-type-itanium = itanium itanium1 merced ; .cpu-type-itanium2 = itanium2 mckinley ; .cpu-type-arm = armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312 armv7 armv7s ; # Known toolset versions, in order of preference. .known-versions = 14.0 12.0 11.0 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1 7.1toolkit 7.0 6.0 ; # Version aliases. .version-alias-6 = 6.0 ; .version-alias-6.5 = 6.0 ; .version-alias-7 = 7.0 ; .version-alias-8 = 8.0 ; .version-alias-9 = 9.0 ; .version-alias-10 = 10.0 ; .version-alias-11 = 11.0 ; .version-alias-12 = 12.0 ; .version-alias-14 = 14.0 ; # Names of registry keys containing the Visual C++ installation path (relative # to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft"). .version-6.0-reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++" ; .version-7.0-reg = "VisualStudio\\7.0\\Setup\\VC" ; .version-7.1-reg = "VisualStudio\\7.1\\Setup\\VC" ; .version-8.0-reg = "VisualStudio\\8.0\\Setup\\VC" ; .version-8.0express-reg = "VCExpress\\8.0\\Setup\\VC" ; .version-9.0-reg = "VisualStudio\\9.0\\Setup\\VC" ; .version-9.0express-reg = "VCExpress\\9.0\\Setup\\VC" ; .version-10.0-reg = "VisualStudio\\10.0\\Setup\\VC" ; .version-10.0express-reg = "VCExpress\\10.0\\Setup\\VC" ; .version-11.0-reg = "VisualStudio\\11.0\\Setup\\VC" ; .version-12.0-reg = "VisualStudio\\12.0\\Setup\\VC" ; .version-14.0-reg = "VisualStudio\\14.0\\Setup\\VC" ; # Visual C++ Toolkit 2003 does not store its installation path in the registry. # The environment variable 'VCToolkitInstallDir' and the default installation # path will be checked instead. .version-7.1toolkit-path = "Microsoft Visual C++ Toolkit 2003" "bin" ; .version-7.1toolkit-env = VCToolkitInstallDir ; # Path to the folder containing "cl.exe" relative to the value of the # corresponding environment variable. .version-7.1toolkit-envpath = "bin" ; # Auto-detect all the available msvc installations on the system. auto-detect-toolset-versions ; # And finally trigger the actual Boost Build toolset registration. register-toolset ;