From cd11383bb811c515171e0a7731bd210fb75cc92f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jurko=20Gospodneti=C4=87?= Date: Mon, 25 Aug 2008 01:47:54 +0000 Subject: [PATCH] Refactored and better commented the Boost Build msvc toolset module as it grew to be quite large and lose its structure while even more features are being planned for it. No functional changes. Organized content into: module inclusions, public rules, class definitions, local rules and finally startup code, in that order. Rules inside a single group ordered alphabetically. Mostly standardized global variable naming style. Extracted all toolset, flag & generator registrations into a single helper rule. Extracted all the msvc version auto-detection code into a single local helper rule. toolset.flag rule now referenced by its full name. Minor stylistic changes. [SVN r48361] --- v2/tools/msvc.jam | 1324 ++++++++++++++++++++++++--------------------- 1 file changed, 713 insertions(+), 611 deletions(-) diff --git a/v2/tools/msvc.jam b/v2/tools/msvc.jam index 5e2fba8ce..d38bb95d4 100644 --- a/v2/tools/msvc.jam +++ b/v2/tools/msvc.jam @@ -4,75 +4,64 @@ # Copyright (c) 2006 Bojan Resnik. # Copyright (c) 2006 Ilya Sokolov. # Copyright (c) 2007 Rene Rivera +# Copyright (c) 2008 Jurko Gospodnetic # # Use, modification and distribution is subject to the Boost Software # License Version 1.0. (See accompanying file LICENSE_1_0.txt or # 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 property ; -import generators ; -import os ; -import type ; -import toolset : flags ; +import common ; import errors ; import feature ; -import path ; -import common ; -import rc ; -import midl ; +import generators ; import mc ; +import midl ; +import property ; +import os ; +import path ; import pch ; - -if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] -{ - .debug-configuration = true ; -} - -feature.extend toolset : msvc ; - -feature.subfeature toolset msvc : vendor - : intel - : propagated optional - # intel and msvc supposedly have link-compatible objects... remains - # to be seen, though ;-) - ; - -# List of all registered configurations -.versions = [ new configurations ] ; - -# 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 ; - -RM = [ common.rm-command ] ; -nl = " -" ; +import rc ; +import toolset ; +import type ; -# Initialize the toolset for a specific version. 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: +################################################################################ +# +# 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 paramater can be ommited: +# The version parameter may be ommited: # # using msvc : : Z:/foo/bar/cl.exe ; # -# Two special version keywords may be supplied: -# - all - all detected versions will be registered; +# 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 -# all possible cases: +# the possible scenarios: # # Nothing "x.y" # Passed Nothing "x.y" detected, detected, @@ -86,8 +75,9 @@ nl = " # "x.y" - refers to a detected version; # "a.b" - refers to an undetected version. # -# Note: for free VC7.1 tools, we do not correctly find vcvars32.bar when user -# explicitly provides a path. +# 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 @@ -141,27 +131,34 @@ rule init ( { options += $(command) ; } - configure $(version) : $(options) ; } # 'configure' is a newer version of 'init'. The parameter 'command' is passed as -# a part of the 'options' list. +# a part of the 'options' list. See the 'init' rule comment for more detailed +# information. # rule configure ( version ? : options * ) { switch $(version) { - case all : + case "all" : if $(options) { - errors.error "msvc: options should be empty when 'all' is specified" ; + errors.error "msvc: Options should be empty when '$(version)'" + "is specified" ; } - # Use all detected versions. - for local v in [ $(.versions).all ] + # Configure (i.e. mark as used) all registered versions. + local all-versions = [ $(.versions).all ] ; + 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) ; } @@ -174,48 +171,422 @@ rule configure ( version ? : options * ) } -# Supported CPU architectures. -.cpu-arch-i386 = - / - /32 - x86/ - x86/32 ; - -.cpu-arch-amd64 = - /64 - x86/64 ; - -.cpu-arch-ia64 = - ia64/ - ia64/64 ; - - -# 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. +# 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. # -local rule locate-default-setup ( command : parent : setup-name ) +rule configure-version-specific ( toolset : version : conditions ) { - local result = [ GLOB $(command) $(parent) : $(setup-name) ] ; - if $(result[1]) + 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. + # above). + if ! [ MATCH ^(6\\.) : $(version) ] { - return $(result[1]) ; + 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)/i386 : /G3 ; + 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 ; + } + toolset.pop-checking-for-flags-module ; +} + + +# 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 ; } } +# 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: +# +# -coff generate COFF format object file (compatible with cl.exe output) +# -Zp4 align structures to 4 bytes +# -Cp preserve case of user identifiers +# -Cx preserve case in publics, externs +# +actions compile.asm +{ + $(.ASM) -nologo -c -coff -Zp4 -Cp -Cx $(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.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) ; + } +} + + +# Action for running the C/C++ compiler without using precompiled headers. +# +actions compile-c-c++ +{ + $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER) +} + + +rule compile-c-c++ ( targets + : sources * ) +{ + DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ; + DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ; +} + + +# 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=)" -Yl"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote))" $(.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=)" -Yl"__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++.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.dll ( targets + : sources * : properties * ) +{ + DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ; +} + + +# 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% + if exist "$(<[1]).manifest" ( + $(.MT) -manifest "$(<[1]).manifest" "-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% + if exist "$(<[1]).manifest" ( + $(.MT) -manifest "$(<[1]).manifest" "-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")" + 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")" + if test -e "$(<[1]).manifest"; then + $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2" + fi + } +} + + +################################################################################ +# +# 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) + { + 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) ] ; + } + } +} + + +# 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 detected version. + # 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 were - # detected. + # Note: 'version' can still be empty at this point if no versions have + # been auto-detected. version ?= "default" ; } @@ -232,7 +603,8 @@ local rule configure-really ( version ? : options * ) # identical sets of options are used. if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] ) { - errors.error "msvc: the toolset version '$(version)' already configured." ; + errors.error "msvc: Toolset version '$(version)' already" + "configured." ; } } else @@ -247,7 +619,8 @@ local rule configure-really ( version ? : options * ) $(.versions).use $(version) ; # Generate conditions and save them. - local conditions = [ common.check-init-parameters msvc : version $(v) ] ; + local conditions = [ common.check-init-parameters msvc : version $(v) ] + ; $(.versions).set $(version) : conditions : $(conditions) ; @@ -264,6 +637,8 @@ local rule configure-really ( version ? : options * ) { # 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 9)" : $(command) ] { version = 9.0 ; @@ -276,7 +651,8 @@ local rule configure-really ( version ? : options * ) { version = 7.1 ; } - else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" : $(command) ] + else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" : + $(command) ] { version = 7.1toolkit ; } @@ -346,7 +722,8 @@ local rule configure-really ( version ? : options * ) global-setup = $(global-setup[1]) ; if ! $(below-8.0) { - global-setup ?= [ locate-default-setup $(command) : $(parent) : vcvarsall.bat ] ; + global-setup ?= [ locate-default-setup $(command) : $(parent) : + vcvarsall.bat ] ; } local default-setup-amd64 = vcvarsx86_amd64.bat ; @@ -383,7 +760,7 @@ local rule configure-really ( version ? : options * ) } local setup-prefix = "call " ; - local setup-suffix = " >nul"$(nl) ; + local setup-suffix = " >nul"$(.nl) ; if ! [ os.name ] in NT { setup-prefix = "cmd.exe /S /C call " ; @@ -486,113 +863,20 @@ local rule configure-really ( version ? : options * ) toolset.flags msvc .CC.FILTER $(cpu-conditions) : "|" $(cc-filter) ; } } + # Set version-specific flags. configure-version-specific msvc : $(version) : $(conditions) ; } } -# 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 -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 - conroe conroe-xe conroe-l allendale mermon mermon-xe kentsfield kentsfield-xe - penryn wolfdale yorksfield nehalem ; -cpu-type-amd64 = k8 opteron athlon64 athlon-fx ; - -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 ; - - -# 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 msvc version is at 7.*, - # add those options explicitly. We can be sure either if user specified - # version 7.* explicitly, or if the installation path contain 7.* (checked - # above). - 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)/i386 : /G3 ; - 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 ; - } - toolset.pop-checking-for-flags-module ; -} - - # 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 ] ] ; + local path = [ feature.get-values : [ $(.versions).get $(version) + : options ] ] ; if $(path) { @@ -628,7 +912,7 @@ local rule default-path ( version ) # Returns either the default installation path (if 'version' is not empty) or # list of all known default paths (if no version is given) # -rule default-paths ( version ? ) +local rule default-paths ( version ? ) { local possible-paths ; @@ -648,417 +932,172 @@ rule default-paths ( version ? ) } -# 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-linker msvc.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : msvc ; -generators.register-linker msvc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB : msvc ; - -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 ; - -# 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 ; - -# pch support - -feature.feature pch-source : : free dependency ; - -class msvc-pch-generator : pch-generator +local rule get-rspline ( target : lang-opt ) { - 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) - { - 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) ; - } + CC_RSPLINE on $(target) = [ on $(target) return $(lang-opt) -U$(UNDEFS) + $(CFLAGS) $(C++FLAGS) $(OPTIONS) -c $(.nl)-D$(DEFINES) + $(.nl)\"-I$(INCLUDES:W)\" ] ; } -# Note: the 'H' source type will catch both '.h' header and '.hpp' header. The -# latter have HPP type, but HPP type is 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 ; - -flags msvc.compile PCH_FILE on : ; -flags msvc.compile PCH_SOURCE on : ; -flags msvc.compile PCH_HEADER on : ; - +# Unsafe worker rule for the register-toolset() rule. Must not be called +# multiple times. # -# Declare flags and action for compilation +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 ; + + # Precompiled header (PCH) support feature. + feature.feature pch-source : : free dependency ; + + # 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-linker msvc.link : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : msvc ; + generators.register-linker msvc.link.dll : OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB : msvc ; + + 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 ; + + # 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. + # + feature.feature debug-store : object database : propagated ; + + 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.c OPTIONS : ; + toolset.flags msvc.compile.c++ OPTIONS : ; + + toolset.flags msvc.compile PDB_CFLAG on/database : /Fd ; # not used yet + + 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 ; + + # 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.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. # -feature.feature debug-store : object database : propagated ; - -flags msvc.compile CFLAGS speed : /O2 ; -flags msvc.compile CFLAGS space : /O1 ; - -flags msvc.compile CFLAGS $(.cpu-arch-ia64)/$(cpu-type-itanium) : /G1 ; -flags msvc.compile CFLAGS $(.cpu-arch-ia64)/$(cpu-type-itanium2) : /G2 ; - -flags msvc.compile CFLAGS on/object : /Z7 ; -flags msvc.compile CFLAGS on/database : /Zi ; -flags msvc.compile CFLAGS off : /Od ; -flags msvc.compile CFLAGS off : /Ob0 ; -flags msvc.compile CFLAGS on : /Ob1 ; -flags msvc.compile CFLAGS full : /Ob2 ; - -flags msvc.compile CFLAGS on : /W3 ; -flags msvc.compile CFLAGS off : /W0 ; -flags msvc.compile CFLAGS all : /W4 ; -flags msvc.compile CFLAGS on : /WX ; - -flags msvc.compile C++FLAGS on/off/off : /EHs ; -flags msvc.compile C++FLAGS on/off/on : /EHsc ; -flags msvc.compile C++FLAGS on/on/off : /EHa ; -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 expliclty so we do not have to depend on this -# default behaviour. -flags msvc.compile CFLAGS on : /GR ; -flags msvc.compile CFLAGS off : /GR- ; -flags msvc.compile CFLAGS off/shared : /MD ; -flags msvc.compile CFLAGS on/shared : /MDd ; - -flags msvc.compile CFLAGS off/static/multi : /MT ; -flags msvc.compile CFLAGS on/static/multi : /MTd ; - -flags msvc.compile.c OPTIONS : ; -flags msvc.compile.c++ OPTIONS : ; - -flags msvc.compile PDB_CFLAG on/database : /Fd ; # not used yet - -flags msvc.compile DEFINES ; -flags msvc.compile UNDEFS ; -flags msvc.compile INCLUDES ; - - -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)\" ] ; -} - - -rule compile-c-c++ ( targets + : sources * ) -{ - DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ; - DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ; -} - - -actions compile-c-c++ -{ - $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER) -} - - -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++ ( targets + : sources * : properties * ) -{ - get-rspline $(targets) : -TP ; - compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; -} - - -actions compile-c-c++-pch-s -{ - $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" -Yl"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" $(.CC.FILTER) -} - - -# Needed only to avoid messing up Emacs syntax highlighting in the messy -# N-quoted code below. -quote = "\"" ; - -actions compile-c-c++-pch -{ - $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" -Yl"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include $(quote)$(>[1]:D=)$(quote))" $(.CC.FILTER) -} - - -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) ; - } -} - - -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) ; - } -} - - -actions compile.rc -{ - $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)" -} - - -# See midl.jam for details. -TOUCH_FILE = [ common.file-touch-command ] ; - - -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)" -} - - -# Declare flags and action for the assembler - -flags msvc.compile.asm USER_ASMFLAGS : ; - - -# For the assembler the following options are turned on by default: +# 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. # -# -coff generate COFF format object file (compatible with cl.exe output) -# -Zp4 align structures to 4 bytes -# -Cp preserve case of user identifiers -# -Cx preserve case in publics, externs - -actions compile.asm +local rule locate-default-setup ( command : parent : setup-name ) { - $(.ASM) -nologo -c -coff -Zp4 -Cp -Cx $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)" -} - - -# Declare flags and action for linking. -flags msvc.link PDB_LINKFLAG on/database : /PDB: ; # not used yet -flags msvc.link LINKFLAGS on : /DEBUG ; -flags msvc.link DEF_FILE ; -# The linker disables the default optimizations when using /DEBUG. We have to -# enable them manually for release builds with debug symbols. -flags msvc LINKFLAGS on/off : /OPT:REF,ICF ; - -flags msvc LINKFLAGS console : /subsystem:console ; -flags msvc LINKFLAGS gui : /subsystem:windows ; -flags msvc LINKFLAGS wince : /subsystem:windowsce ; -flags msvc LINKFLAGS native : /subsystem:native ; -flags msvc LINKFLAGS auto : /subsystem:posix ; - -flags msvc.link OPTIONS ; -flags msvc.link LINKPATH ; - -flags msvc.link FINDLIBS_ST ; -flags msvc.link FINDLIBS_SA ; -flags msvc.link LIBRARY_OPTION msvc : "" : unchecked ; -flags msvc.link LIBRARIES_MENTIONED_BY_FILE : ; - -flags msvc.archive AROPTIONS ; - - -rule link.dll ( targets + : sources * : properties * ) -{ - DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ; -} - - -# 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 + local result = [ GLOB $(command) $(parent) : $(setup-name) ] ; + if $(result[1]) { - 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")" + return $(result[1]) ; } } -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")" - } -} - - -# 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% - if exist "$(<[1]).manifest" ( - $(.MT) -manifest "$(<[1]).manifest" "-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% - if exist "$(<[1]).manifest" ( - $(.MT) -manifest "$(<[1]).manifest" "-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")" - 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")" - if test -e "$(<[1]).manifest"; then - $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);2" - fi - } -} - - -actions compile.mc -{ - $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)" -} - - -# -# Autodetection code -# detects versions listed as '.known-versions' using registry, environment -# and checking default paths. Supports both native Windows and Cygwin. -# - -.ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ; - -.known-versions = 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 ; - -# Name of the registry key that contains 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" ; - -# Visual C++ Toolkit 2003 do 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" ; # Validates given path, registers found configuration and prints debug @@ -1083,37 +1122,100 @@ local rule register-configuration ( version : path ? ) } } -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.native [ path.join [ path.make-NT $(vc-path[1]) ] "bin" ] ] ; - register-configuration $(i) : $(vc-path[1]) ; - } - } - } +################################################################################ +# +# 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 ] ; -# Check environment and default installation paths. +# List of all registered configurations. +.versions = [ new configurations ] ; -for local i in $(.known-versions) -{ - if ! $(i) in [ $(.versions).all ] - { - register-configuration $(i) : [ default-path $(i) ] ; - } -} +# Supported CPU architectures. +.cpu-arch-i386 = + / + /32 + x86/ + x86/32 ; + +.cpu-arch-amd64 = + /64 + x86/64 ; + +.cpu-arch-ia64 = + ia64/ + ia64/64 ; + + +# 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 conroe conroe-xe conroe-l allendale mermon + mermon-xe kentsfield kentsfield-xe penryn wolfdale + yorksfield nehalem ; +.cpu-type-amd64 = k8 opteron athlon64 athlon-fx ; +.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 ; + + +# Known toolset versions, in order of preference. +.known-versions = 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 ; + +# 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" ; + +# 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" ; + + +# We try to auto-detect all the available msvc installations on the system +# directly on module import. +auto-detect-toolset-versions ; + + +# And finally trigger the actual Boost Build toolset registration. +# +# TODO: This should later be triggered lazily to avoid registering the toolset +# in case none of its versions have been configured successfully. +register-toolset ;