# Copyright David Abrahams 2003. Permission to copy, use, # modify, sell and distribute this software is granted provided this # copyright notice appears in all copies. This software is provided # "as is" without express or implied warranty, and with no claim as # to its suitability for any purpose. import property ; import generators ; import os ; import type ; import toolset : flags ; import errors : error ; import feature : feature ; import path ; import sequence : unique ; 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 ;-) ; feature.subfeature toolset msvc : version : # 6 7 7.1 # known subvalues : propagated implicit # versions of msvc are link-compatible # link-incompatible ; # 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 : X:/some_dir ; # using msvc : 7.0 : Y:/some_dir ; # using msvc : : Z:/some_dir # If you have "msvc-6.5" in build request, the version from X: drive will be used, # and if you put only "msvc", then drive "Z:" will be used. Note that it's not possible # the specify that by default, version 7.0 must be used --- you should use 'using' # without version number for that effect. # # version -- the msvc version which is being configured. When omitted # the tools invoked when no explicit version is given will be configured. # path -- the path to root directory of msvc installation. 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. # # When invoking tools, we'll first run vcvars32.bat from the configured path and # then cl/link, without path. rule init ( version ? : path ? : vendor ? : setup ? compiler ? linker ? ) { compiler ?= cl ; linker ?= link ; if $(version) { feature.extend-subfeature toolset msvc : version : $(version) ; } if $(vendor) && ( $(vendor) != intel ) { feature.extend-subfeature toolset msvc : vendor : $(vendor) ; } # setup will be used iff a path has been specified. If setup is # not specified, vcvars32.bat will be used instead. setup ?= vcvars32.bat ; if ! $(path) { setup = [ locate $(version) : $(vendor) ] ; } else { # Don't bother with any searches. User has provided a path, # and we assume it's correct. # TODO: actually, it's better to check the path even in this # case. setup = $(path)\\bin\\$(setup) ; } # CONSIDER: What's the point of 'call'. Can we invoke the script directly? setup = "call \""$(setup)"\" > nul " ; if [ os.name ] = NT { setup = $(setup)" ; " ; } else { setup = "cmd /S /C "$(setup)" \"&&\" " ; } # prefix with setup, or quoted path if any local prefix = $(setup) ; if $(version) { vendor = $(vendor)- ; vendor ?= "" ; local condition = -$(vendor)$(version) ; condition ?= "" ; condition = msvc$(condition) ; flags msvc.compile .CC $(condition) : $(prefix)$(compiler) ; flags msvc.link .LD $(condition) : $(prefix)$(linker) ; flags msvc.archive .LD $(condition) : $(prefix)$(linker) ; } else { # When version is not specified, we cannot form any useful # condition. Since subfeatures don't have defaults, we can't # use 'unspecified' as version. Therefore, just set global # variables in this module. .CC = $(prefix)$(compiler) ; .LD = $(prefix)$(linker) ; } } .CC = cl ; .LD = LINK ; # Attempts to find the vcvars32.bat script for the relevant version, and returns the path # to it. If path is not found, issues an error. # If there are several possibilities, returns arbitrary one, after issuing a # warning message. local rule locate ( version ? : vendor ? ) { local possible-paths ; # Append the list of relevant default locations. # We know default locations only for msvc, not for alternative vendors if ! $(vendor) { local version-6-path = "c:\\Program Files\\Microsoft Visual Studio\\VC98" ; local version-7-path = "c:\\Program Files\\Microsoft Visual Studio .NET\\VC7" ; local version-7.0-path = $(version-7-path) ; local version-7.1-path = "c:\\Program Files\\Microsoft Visual Studio .NET 2003\\VC7" ; if $(version) { local v = [ MATCH ^(6|[^6].*) : $(version) ] ; possible-paths += $(version-$(v)-path) ; } else { possible-paths += $(version-7.1-path) $(version-7.0-path) $(version-6-path) ; } # The vccars32.bat is actually in "bin" directory. possible-paths = $(possible-paths)\\bin ; } # Append PATH possible-paths += [ modules.peek : PATH Path path ] ; # Search now local setup = [ GLOB $(possible-paths) : vcvars32.bat ] ; # Try to avoid reporting ambiguity when there's several occurences # of the same path, probably differing by case. setup = [ unique $(setup:L) ] ; if $(setup[2]) && ! ( --quiet in [ modules.peek : ARGV ] ) { ECHO warning: toolset msvc $(vendor) $(version) initialization: ; ECHO "warning: several msvc installations found." ; ECHO "$(setup:D)" ; ECHO "warning: using the one in $(setup[1]:D)." ; setup = $(setup[1]) ; } if ! $(setup) { error toolset msvc $(vendor) $(version) initialization: : couldn't find compiler in $(possible-paths) ; } if $(.debug-configuration) { ECHO "notice: msvc $(version:E=) $(vendor:E="")" ; ECHO "notice: found at \"$(setup:D)\"" ; } return $(setup) ; } # 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 "" : RSP : EXE : msvc ; generators.register-linker msvc.link "" : RSP : SHARED_LIB IMPORT_LIB : msvc ; generators.register-standard msvc.archive : RSP : STATIC_LIB : msvc ; generators.register-c-compiler msvc.compile : CPP : OBJ : msvc ; generators.register-c-compiler msvc.compile : C : OBJ : msvc ; # # Declare flags and action for compilation # feature.feature debug-store : object database : propagated ; flags msvc.compile CFLAGS on/object : /Z7 ; flags msvc.compile CFLAGS on/database : /Zi ; flags msvc.compile CFLAGS off : /Od ; flags msvc.compile CFLAGS speed : /Ogity /O2 /Gs ; flags msvc.compile CFLAGS space : /Ogisy /O1 /Gs ; flags msvc.compile CFLAGS off : /Ob0 ; flags msvc.compile CFLAGS on : /Ob1 ; flags msvc.compile CFLAGS full : /Ob2 ; flags msvc.compile CFLAGS on : /GX ; 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/single : /ML ; flags msvc.compile CFLAGS on/static/single : /MLd ; flags msvc.compile CFLAGS off/static/multi : /MT ; flags msvc.compile CFLAGS on/static/multi : /MTd ; flags msvc.compile CFLAGS CPP : /GX ; flags msvc.compile USER_CFLAGS : ; 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 WHATEVER ; actions compile { $(.CC) /Zm800 -nologo -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(USER_CFLAGS) -I"$(INCLUDES)" -c -Fo"$(<)" "$(>)" } # Declare flags and action for linking flags msvc.link PDB_LINKFLAG on/database : /PDB: ; # not used yet flags msvc.link LINKFLAGS on : /DEBUG ; # 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 NEEDLIBS ; flags msvc LINKFLAGS LIB/shared : /DLL ; toolset.flags msvc.link USER_LINKFLAGS ; toolset.flags msvc.link LINKPATH ; toolset.flags msvc.link FINDLIBS ; flags builtin.response-file LIBRARY_PATH_OPTION msvc : /LIBPATH: : unchecked ; flags builtin.response-file LIBRARY_OPTION msvc : "" : unchecked ; # 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. # Declare action for creating static libraries if [ os.name ] in NT { .implib = "/INCREMENTAL:NO /IMPLIB:" ; actions archive { if exist "$(<)" set _$(<:B)_="$(<)" $(.LD) /lib /out:"$(<)" %_$(<:B)_% @"$(>)" } } else # CYGWIN { rule link ( target implib ? : sources + : properties * ) { if $(implib) { .implib on $(<) = "/INCREMENTAL:NO /IMPLIB:" ; } .cygpath = "cygpath -d " ; } actions archive { _bbv2_out_="$(<)" if test -f "$_bbv2_out_" ; then _bbv2_existing_="$(<:W)" fi $(.LD) /lib "/out:$(<:W)" $_bbv2_existing_ @"$(>:W)" } } actions link { $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" $(.implib)"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" "$(FINDLIBS:S=.lib)" $(USER_LINKFLAGS) @"$(>:W)" }