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 ;