# Copyright (c) 2003 David Abrahams. # Copyright (c) 2005 Vladimir Prus. # Copyright (c) 2005 Alexey Pakhunov. # Copyright (c) 2006 Bojan Resnik. # # 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) import property ; import generators ; import os ; import type ; import toolset : flags ; import errors : error ; import feature : feature get-values ; import path ; import sequence : unique ; import common ; import "class" : new ; import rc ; import midl ; import mc ; 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 ; RM = [ common.rm-command ] ; nl = " " ; # 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: # # using msvc : 6.5 : cl.exe ; # using msvc : 7.0 : Y:/foo/bar/cl.exe ; # # The version paramater can be ommited: # # using msvc : : Z:/foo/bar/cl.exe ; # # Two special version keywords may be supplied: # - all - all detected versions will be registered; # - 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: # # Nothing "x.y" # Passed Nothing "x.y" detected, detected, # version detected detected cl.exe in path cl.exe in path # # default Error Use "x.y" Create "default" Use "x.y" # all None Use all None Use all # x.y - Use "x.y" - Use "x.y" # a.b Error Error Create "a.b" Create "a.b" # # "x.y" - refers to a detected version; # "a.b" - refers to an undetected version. # # Note: for free VC7.1 tools, we don't correctly find vcvars32.bar when user # explicitly provides a path. rule init ( version ? # the msvc version which is being configured. When omitted # the tools invoked when no explicit version is given will be configured. : command * # the command to invoke the compiler. If not specified: # - if version is given, default location for that version will be searched # # - if version is not given, default locations for 7.1, 7.0 and 6.* will # be searched # # - if compiler is not found in default locations, PATH will be searched. : options * # options can include , , , and ) { if $(command) { options += $(command) ; } configure $(version) : $(options) ; } # 'configure' is a newer version of 'init'. The parameter 'command' is passed as # a part of the 'options' list. rule configure ( version ? : options * ) { switch $(version) { case all : if $(options) { error "msvc: options should be empty when 'all' is specified" ; } # use all detected versions for local v in [ $(.versions).all ] { configure-really $(v) ; } case "default" : configure-really : $(options) ; case * : configure-really $(version) : $(options) ; } } # Supported CPU architectures cpu-arch-i386 = / /32 x86/ x86/32 ; cpu-arch-amd64 = /64 x86/64 ; cpu-arch-ia64 = ia64/ ia64/64 ; local rule configure-really ( version ? : options * ) { # If no version supplied use the default configuration. Note that condition # remains versionless. local v = $(version) ; if ! $(v) { # take the first detected version version = [ $(.versions).all ] ; version = $(version[1]) ; # Note: 'version' can still be empty at this point if no versions were # detected. version ?= "default" ; } # Version alias -> real version number if $(.version-alias-$(version)) { version = $(.version-alias-$(version)) ; } # Check whether selected configuration is used already if $(version) in [ $(.versions).used ] { # Allow multiple 'toolset.usage' calls for the same configuration # if the identical sets of options are used if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] ) { error "msvc: the toolset version '$(version)' is configured already" ; } } else { # Register a new configuration $(.versions).register $(version) ; # Add user-supplied to auto-detected options options = [ $(.versions).get $(version) : options ] $(options) ; # Mark the configuration as 'used'. $(.versions).use $(version) ; # Generate condition and save it local condition = [ common.check-init-parameters msvc : version $(v) ] ; $(.versions).set $(version) : condition : $(condition) ; local command = [ get-values : $(options) ] ; # If version is specified, we try to search first in default paths, # and only then in PATH. command = [ common.get-invocation-command msvc : cl.exe : $(command) : [ default-paths $(version) ] : $(version) ] ; common.handle-options msvc : $(condition) : $(command) : $(options) ; if ! $(version) { # Even if version is not explicitly specified, try to detect the version # from the path. if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ] { version = 8.0 ; } else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ] { version = 7.1 ; } else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" : $(command) ] { version = 7.1toolkit ; } else if [ MATCH "(.NET[\/\\]VC7)" : $(command) ] { version = 7.0 ; } else { version = 6.0 ; } } # Generate and register setup command local below-8.0 = [ MATCH ^([67]\\.) : $(version) ] ; local cpu = i386 ; local setup ; local setup-option ; if $(command) { command = [ common.get-absolute-tool-path $(command[-1]) ] ; local parent = [ path.make $(command) ] ; parent = [ path.parent $(parent) ] ; parent = [ path.native $(parent) ] ; # setup will be used if the script name has been specified. # If setup is not specified, a default script will be used instead. setup = [ get-values : $(options) ] ; if ! $(setup) { if $(below-8.0) { setup ?= vcvars32.bat ; } else { setup ?= vcvarsall.bat ; } # The vccars32.bat is actually in "bin" directory. # (except for free VC7.1 tools) setup = [ GLOB $(command) $(parent) : $(setup) ] ; } if $(setup) { # Note Cygwin to Windows translation setup = "\""$(setup[1]:W)"\"" ; if ! $(below-8.0) { cpu = i386 amd64 ia64 ; setup-option = x86 x86_amd64 x86_ia64 ; } } } local prefix = "call " ; local suffix = " >nul " ; if ! [ os.name ] in NT { prefix = "cmd.exe /S /C call " ; suffix = " >nul \"&&\" " ; } command = $(prefix)$(setup)" "$(setup-option:E="")$(suffix) ; # Setup script is not required in some configurations command ?= "" ; # Get tool names (if any) and finish setup compiler = [ get-values : $(options) ] ; compiler ?= cl ; linker = [ get-values : $(options) ] ; linker ?= link ; resource-compiler = [ get-values : $(options) ] ; resource-compiler ?= rc ; assembler = [ get-values : $(options) ] ; assembler ?= ml ; idl-compiler = [ get-values : $(options) ] ; idl-compiler ?= midl ; mc-compiler = [ get-values : $(options) ] ; mc-compiler ?= mc ; manifest-tool = mt ; for local i in 1 2 3 { local c = $(cpu[$(i)]) ; if $(c) { local cond = $(condition)/$(cpu-arch-$(c)) ; if $(.debug-configuration) { ECHO "msvc: condition: '$(cond)', " "command: '$(command[$(i)])'" ; } flags msvc.compile .CC $(cond) : $(command[$(i)])$(compiler) /Zm800 -nologo ; flags msvc.compile .RC $(cond) : $(command[$(i)])$(resource-compiler) ; flags msvc.compile .ASM $(cond) : $(command[$(i)])$(assembler) ; flags msvc.link .LD $(cond) : $(command[$(i)])$(linker) /NOLOGO /INCREMENTAL:NO ; flags msvc.archive .LD $(cond) : $(command[$(i)])$(linker) /lib /NOLOGO ; flags msvc.compile .IDL $(cond) : $(command[$(i)])$(idl-compiler) ; flags msvc.compile .MC $(cond) : $(command[$(i)])$(mc-compiler) ; if ! [ os.name ] in NT { flags msvc.link .MT $(cond) : $(command[$(i)])$(manifest-tool) -nologo ; } else { flags msvc.link .MT $(cond) : $(manifest-tool) -nologo ; } } } # Set version-specific flags configure-version-specific msvc : $(version) : $(condition) ; } } # Supported CPU types 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 ; 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 that are dependent on the version ot # compiler. # - 'version' is the version of compiler in N.M format. # - 'condition' is the property set to be used as condition for flag # - '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 : condition ) { 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're 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.* (this is checked above). if ! [ MATCH ^(6\\.) : $(version) ] { flags $(toolset).compile CFLAGS $(condition) : /Zc:forScope /Zc:wchar_t ; flags $(toolset).compile.c++ C++FLAGS $(condition) : /wd4675 ; # disable the function is deprecated warning # Some version of msvc have a bug, that cause deprecation # warning to be emitted even with /W0 flags $(toolset).compile CFLAGS $(condition)/off : /wd4996 ; # 64-bit compatibility warning flags $(toolset).compile CFLAGS $(condition)/all : /Wp64 ; } # # Processor-specific optimization # if [ MATCH ^([67]) : $(version) ] { # 8.0 deprecates some of the options flags $(toolset).compile CFLAGS $(condition)/speed $(condition)/space : /Ogiy /Gs ; flags $(toolset).compile CFLAGS $(condition)/speed : /Ot ; flags $(toolset).compile CFLAGS $(condition)/space : /Os ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/ : /GB ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/i386 : /G3 ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/i486 : /G4 ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/$(cpu-type-g5) : /G5 ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/$(cpu-type-g6) : /G6 ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-i386)/$(cpu-type-g7) : /G7 ; # Improve floating-point accuracy. Otherwise, some of C++ Boost's # "math" tests will fail. flags $(toolset).compile CFLAGS $(condition) : /Op ; # 7.1 and below have single-threaded static RTL flags $(toolset).compile CFLAGS $(condition)/off/static/single : /ML ; flags $(toolset).compile CFLAGS $(condition)/on/static/single : /MLd ; } else { # 8.0 adds some more options flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-amd64)/ : /favor:blend ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-amd64)/$(cpu-type-em64t) : /favor:EM64T ; flags $(toolset).compile CFLAGS $(condition)/$(cpu-arch-amd64)/$(cpu-type-amd64) : /favor:AMD64 ; # 8.0 only has multi-threaded static RTL flags $(toolset).compile CFLAGS $(condition)/off/static/single : /MT ; flags $(toolset).compile CFLAGS $(condition)/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 = [ get-values : [ $(.versions).get $(version) : options ] ] ; if $(path) { path = $(path:D) ; } else { # Check environment if $(.version-$(version)-env) { local vc-path = [ os.environ $(.version-$(version)-env) ] ; if $(vc-path) { vc-path = [ path.make $(vc-path) ] ; vc-path = [ path.join $(vc-path) $(.version-$(version)-envpath) ] ; vc-path = [ path.native $(vc-path) ] ; path = $(vc-path) ; } } # Check default path if ! $(path) && $(.version-$(version)-path) { path = [ path.native [ path.join $(.ProgramFiles) $(.version-$(version)-path) ] ] ; } } return $(path) ; } # Returns either the default installation path (if 'version' is not empty) or list of all # known default paths (if no version is given) rule default-paths ( version ? ) { local possible-paths ; if $(version) { possible-paths += [ default-path $(version) ] ; } else { for local i in $(.known-versions) { possible-paths += [ default-path $(i) ] ; } } return $(possible-paths) ; } # Declare generators # is it possible to combine these? # make the generators non-composing, so that they don't convert each source # into 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 ; generators.register [ new pch-generator msvc.compile.pch : PCHEADER : OBJ PCH : msvc ] ; # # Declare flags and action for compilation # 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 ; flags msvc.compile CFLAGS on : /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 ; flags msvc.compile PCH_SOURCE ; flags msvc.compile PCH_HEADER on : ; flags msvc.compile PCH_FILE on : ; 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)\" ] ; } 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))" } 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[1]) : -TP ; compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ; } actions compile-pch { $(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[1]:W)" -Yc"$(>[1]:D=)" -Yl"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[2]:W)" $(CC_RSPLINE))" } rule compile.pch ( targets + : sources * : properties * ) { DEPENDS $(<) : [ on $(<) return $(PCH_SOURCE) ] ; get-rspline $(targets[1]) : -TP ; compile-pch $(targets) : $(sources) [ on $(<) return $(PCH_SOURCE) ] ; } actions compile.rc { $(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES)" -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)" $(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: # # -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)" } # 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. Whe 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 { if exist "$(<[1])" DEL "$(<[1])" $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(nl)"$(>)" $(nl)$(LIBRARIES_MENTIONED_BY_FILE) $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.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:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")" } } # incremental linking a DLL causes no end of problems: if the # actual exports don't change, the import .lib file is never # updated. Therefore, the .lib is always out-of-date and gets # rebuilt every time. I'm not sure that incremental linking is # such a great idea in general, but in this case I'm sure we # don't want it. # Windows Manifests is a new way to specify dependencies # on managed DotNet assemblies and Windows native DLLs. The # manifests are embedded as resourses and are useful in # any PE targets (both DLL and EXE) if [ os.name ] in NT { actions link bind DEF_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:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")" if exist "$(<[1]).manifest" ( $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1" ) } actions link.dll bind DEF_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:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")" if exist "$(<[1]).manifest" ( $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2" ) } } else { actions link bind DEF_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:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.lib)")" if test -e "$(<[1]).manifest"; then $(.MT) -manifest "$(<[1]:W).manifest" "-outputresource:$(<[1]:W);1" fi } actions link.dll bind DEF_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:S=.lib)" $(nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA:S=.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 = 8.0 8.0express 7.1 7.1toolkit 7.0 6.0 ; # Version aliases .version-alias-6 = 6.0 ; .version-alias-7 = 7.0 ; .version-alias-8 = 8.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" ; # 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 information # about it. local rule register-configuration ( version : path ? ) { if $(path) { local command = [ GLOB $(path) : cl.exe ] ; if $(command) { if $(.debug-configuration) { ECHO "notice: msvc-$(version) detected, command: '$(command)'" ; } $(.versions).register $(version) ; $(.versions).set $(version) : options : $(command) ; } } } 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 = [ W32_GETREG "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"$(.version-$(i)-reg) : "ProductDir" ] ; if $(vc-path) { vc-path = [ path.native [ path.join [ path.make-NT $(vc-path) ] "bin" ] ] ; register-configuration $(i) : $(vc-path) ; } } } } # Check environment and default installation paths for local i in $(.known-versions) { if ! $(i) in [ $(.versions).all ] { register-configuration $(i) : [ default-path $(i) ] ; } }