1 # Copyright (c) 2003 David Abrahams.
2 # Copyright (c) 2005 Vladimir Prus.
3 # Copyright (c) 2005 Alexey Pakhunov.
4 # Copyright (c) 2006 Bojan Resnik.
5 # Copyright (c) 2006 Ilya Sokolov.
6 # Copyright (c) 2007 Rene Rivera
7 # Copyright (c) 2008 Jurko Gospodnetic
8 # Copyright (c) 2011 Juraj Ivancic
10 # Use, modification and distribution is subject to the Boost Software
11 # License Version 1.0. (See accompanying file LICENSE_1_0.txt or
12 # http://www.boost.org/LICENSE_1_0.txt)
14 ################################################################################
16 # MSVC Boost Build toolset module.
17 # --------------------------------
19 # All toolset versions need to have their location either auto-detected or
20 # explicitly specified except for the special 'default' version that expects the
21 # environment to find the needed tools or report an error.
23 ################################################################################
25 from os import environ
32 from b2.tools import common, rc, pch, builtin, mc, midl
33 from b2.build import feature, type, toolset, generators, property_set
34 from b2.build.property import Property
35 from b2.util import path
36 from b2.manager import get_manager
37 from b2.build.generators import Generator
38 from b2.build.toolset import flags
39 from b2.util.utility import to_seq, on_windows
40 from b2.tools.common import Configurations
47 __debug = "--debug-configuration" in bjam.variable("ARGV")
51 # It is not yet clear what to do with Cygwin on python port.
56 type.register('MANIFEST', ['manifest'])
57 feature.feature('embed-manifest',['on','off'], ['incidental', 'propagated']) ;
59 type.register('PDB',['pdb'])
61 ################################################################################
65 ################################################################################
67 # Initialize a specific toolset version configuration. As the result, path to
68 # compiler and, possible, program names are set up, and will be used when that
69 # version of compiler is requested. For example, you might have:
71 # using msvc : 6.5 : cl.exe ;
72 # using msvc : 7.0 : Y:/foo/bar/cl.exe ;
74 # The version parameter may be ommited:
76 # using msvc : : Z:/foo/bar/cl.exe ;
78 # The following keywords have special meanings when specified as versions:
79 # - all - all detected but not yet used versions will be marked as used
80 # with their default options.
81 # - default - this is an equivalent to an empty version.
83 # Depending on a supplied version, detected configurations and presence 'cl.exe'
84 # in the path different results may be achieved. The following table describes
85 # the possible scenarios:
88 # Passed Nothing "x.y" detected, detected,
89 # version detected detected cl.exe in path cl.exe in path
91 # default Error Use "x.y" Create "default" Use "x.y"
92 # all None Use all None Use all
93 # x.y - Use "x.y" - Use "x.y"
94 # a.b Error Error Create "a.b" Create "a.b"
96 # "x.y" - refers to a detected version;
97 # "a.b" - refers to an undetected version.
99 # FIXME: Currently the command parameter and the <compiler> property parameter
100 # seem to overlap in duties. Remove this duplication. This seems to be related
101 # to why someone started preparing to replace init with configure rules.
103 def init(version = None, command = None, options = None):
104 # When initialized from
106 # we get version as a single element list i.e. ['x.0'],
107 # but when specified from the command line we get a string i.e. 'x.0'.
108 # We want to work with a string, so unpack the list if needed.
109 is_single_element_list = (isinstance(version,list) and len(version) == 1)
110 assert(version==None or isinstance(version,str) or is_single_element_list)
111 if is_single_element_list:
114 options = to_seq(options)
115 command = to_seq(command)
118 options.append("<command>"+command)
119 configure(version,options)
121 def configure(version=None, options=None):
124 raise RuntimeError("MSVC toolset configuration: options should be empty when '{}' is specified.".format(version))
126 # Configure (i.e. mark as used) all registered versions.
127 all_versions = __versions.all()
130 print "notice: [msvc-cfg] Asked to configure all registered" \
131 "msvc toolset versions when there are none currently" \
134 for v in all_versions:
135 # Note that there is no need to skip already configured
136 # versions here as this will request configure-really rule
137 # to configure the version using default options which will
138 # in turn cause it to simply do nothing in case the version
139 # has already been configured.
141 elif version == "default":
142 configure_really(None,options)
144 configure_really(version, options)
146 def extend_conditions(conditions,exts):
147 return [ cond + '/' + ext for cond in conditions for ext in exts ]
149 def configure_version_specific(toolset_arg, version, conditions):
150 # Starting with versions 7.0, the msvc compiler have the /Zc:forScope and
151 # /Zc:wchar_t options that improve C++ standard conformance, but those
152 # options are off by default. If we are sure that the msvc version is at
153 # 7.*, add those options explicitly. We can be sure either if user specified
154 # version 7.* explicitly or if we auto-detected the version ourselves.
155 if not re.match('^6\\.', version):
156 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS',conditions, ['/Zc:forScope','/Zc:wchar_t'])
157 toolset.flags('{}.compile.c++'.format(toolset_arg), 'C++FLAGS',conditions, ['/wd4675'])
159 # Explicitly disable the 'function is deprecated' warning. Some msvc
160 # versions have a bug, causing them to emit the deprecation warning even
162 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS',extend_conditions(conditions,['<warnings>off']), ['/wd4996'])
163 if re.match('^[78]\\.', version):
164 # 64-bit compatibility warning deprecated since 9.0, see
165 # http://msdn.microsoft.com/en-us/library/yt4xw8fh.aspx
166 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS',extend_conditions(conditions,['<warnings>all']), ['/Wp64'])
169 # Processor-specific optimization.
171 if re.match('^[67]', version ):
172 # 8.0 deprecates some of the options.
173 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<optimization>speed','<optimization>space']), ['/Ogiy', '/Gs'])
174 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<optimization>speed']), ['/Ot'])
175 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<optimization>space']), ['/Os'])
177 cpu_arch_i386_cond = extend_conditions(conditions, __cpu_arch_i386)
178 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>']),['/GB'])
179 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>i386']),['/G3'])
180 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>i486']),['/G4'])
182 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>' + t for t in __cpu_type_g5]), ['/G5'])
183 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>' + t for t in __cpu_type_g6]), ['/G6'])
184 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(cpu_arch_i386_cond,['<instruction-set>' + t for t in __cpu_type_g7]), ['/G7'])
186 # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math"
188 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', conditions, ['/Op'])
190 # 7.1 and below have single-threaded static RTL.
191 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<runtime-debugging>off/<runtime-link>static/<threading>single']), ['/ML'])
192 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<runtime-debugging>on/<runtime-link>static/<threading>single']), ['/MLd'])
194 # 8.0 and above adds some more options.
195 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions, [a + '/<instruction-set>' for a in __cpu_arch_amd64]), ['/favor:blend'])
197 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions, [a + '/<instruction-set>' + t for a in __cpu_arch_amd64 for t in __cpu_type_em64t]), ['/favor:EM64T'])
198 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions, [a + '/<instruction-set>' + t for a in __cpu_arch_amd64 for t in __cpu_type_amd64]), ['/favor:AMD64'])
200 # 8.0 and above only has multi-threaded static RTL.
201 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<runtime-debugging>off/<runtime-link>static/<threading>single']), ['/MT'])
202 toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', extend_conditions(conditions,['<runtime-debugging>on/<runtime-link>static/<threading>single']), ['/MTd'])
204 # Specify target machine type so the linker will not need to guess.
205 toolset.flags('{}.link'.format(toolset_arg), 'LINKFLAGS', extend_conditions(conditions, __cpu_arch_amd64), ['/MACHINE:X64'])
206 toolset.flags('{}.link'.format(toolset_arg), 'LINKFLAGS', extend_conditions(conditions, __cpu_arch_i386), ['/MACHINE:X86'])
207 toolset.flags('{}.link'.format(toolset_arg), 'LINKFLAGS', extend_conditions(conditions, __cpu_arch_ia64), ['/MACHINE:IA64'])
209 # Make sure that manifest will be generated even if there is no
210 # dependencies to put there.
211 toolset.flags('{}.link'.format(toolset_arg), 'LINKFLAGS', extend_conditions(conditions,["<embed-manifest>off"]), ['/MANIFEST'])
214 # Registers this toolset including all of its flags, features & generators. Does
215 # nothing on repeated calls.
217 def register_toolset():
218 if not 'msvc' in feature.values('toolset'):
219 register_toolset_really()
222 engine = get_manager().engine()
224 # this rule sets up the pdb file that will be used when generating static
225 # libraries and the debug-store option is database, so that the compiler
226 # puts all debug info into a single .pdb file named after the library
228 # Poking at source targets this way is probably not clean, but it's the
230 def archive(targets, sources=None, properties=None):
231 bjam.call('set-target-variable',targets,'PDB_NAME', os.path.splitext(targets[0])[0] + '.pdb')
233 # Declare action for creating static libraries. If library exists, remove it
234 # before adding files. See
235 # http://article.gmane.org/gmane.comp.lib.boost.build/4241 for rationale.
237 engine.register_action(
239 '''if exist "$(<[1])" DEL "$(<[1])"
240 $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=
242 $(LIBRARIES_MENTIONED_BY_FILE)
243 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
244 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
247 engine.register_action(
250 $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=
252 $(LIBRARIES_MENTIONED_BY_FILE)
253 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
254 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"'''.format(rm=common.rm_command()),
257 # For the assembler the following options are turned on by default:
259 # -Zp4 align structures to 4 bytes
260 # -Cp preserve case of user identifiers
261 # -Cx preserve case in publics, externs
263 engine.register_action(
265 '$(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)"' )
268 # Equivalent to [ on $(target) return $(prefix)$(var)$(suffix) ]. Note that $(var) can be a list.
269 def expand_target_variable(target,var,prefix=None,suffix=None):
270 list = bjam.call( 'get-target-variable', target, var )
271 return " ".join([ ("" if prefix is None else prefix) + elem + ("" if suffix is None else suffix) for elem in list ])
274 compile_c_cpp_pch = '''$(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" "@($(<[1]:W).cpp:E=#include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote)$(.nl))" $(.CC.FILTER)'''
275 # Action for running the C/C++ compiler using precompiled headers. An already
276 # built source file for compiling the precompiled headers is expected to be
277 # given as one of the source parameters.
278 compile_c_cpp_pch_s = '''$(.CC) @"@($(<[1]:W).rsp:E="$(>[2]:W)" -Fo"$(<[2]:W)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE))" $(.CC.FILTER)'''
280 def get_rspline(targets, lang_opt):
281 result = lang_opt + ' ' + \
282 expand_target_variable(targets, 'UNDEFS', '-U' ) + ' ' + \
283 expand_target_variable(targets, 'CFLAGS' ) + ' ' + \
284 expand_target_variable(targets, 'C++FLAGS' ) + ' ' + \
285 expand_target_variable(targets, 'OPTIONS' ) + ' -c ' + \
286 expand_target_variable(targets, 'DEFINES', '\n-D' ) + ' ' + \
287 expand_target_variable(targets, 'INCLUDES', '\n"-I', '"' )
288 bjam.call('set-target-variable', targets, 'CC_RSPLINE', result)
290 def compile_c(targets, sources = [], properties = None):
291 get_manager().engine().set_target_variable( targets[1], 'C++FLAGS', '' )
292 get_rspline(targets, '-TC')
293 sources += bjam.call('get-target-variable',targets,'PCH_FILE')
294 sources += bjam.call('get-target-variable',targets,'PCH_HEADER')
295 compile_c_cpp(targets,sources)
297 def compile_c_preprocess(targets, sources = [], properties = None):
298 get_manager().engine().set_target_variable( target[1], 'C++FLAGS', '' )
299 get_rspline(targets, '-TC')
300 sources += bjam.call('get-target-variable',targets,'PCH_FILE')
301 sources += bjam.call('get-target-variable',targets,'PCH_HEADER')
302 preprocess_c_cpp(targets,sources)
304 def compile_c_pch(targets, sources = [], properties = []):
305 get_manager().engine().set_target_variable( target[1], 'C++FLAGS', '' )
306 get_rspline([targets[1]], '-TC')
307 get_rspline([targets[2]], '-TC')
308 pch_source = bjam.call('get-target-variable', targets, 'PCH_SOURCE')
309 sources += pch_source
311 get_manager().engine().set_update_action('compile-c-c++-pch-s', targets, sources, properties)
312 get_manager().engine().add_dependency(targets,pch_source)
313 compile_c_cpp_pch_s(targets,sources)
315 get_manager().engine().set_update_action('compile-c-c++-pch', targets, sources, properties)
316 compile_c_cpp_pch(targets,sources)
318 toolset.flags( 'msvc', 'YLOPTION', [], ['-Yl'] )
320 def compile_cpp(targets,sources=[],properties=None):
321 get_rspline(targets,'-TP')
322 sources += bjam.call('get-target-variable',targets,'PCH_FILE')
323 sources += bjam.call('get-target-variable',targets,'PCH_HEADER')
324 compile_c_cpp(targets,sources)
326 def compile_cpp_preprocess(targets,sources=[],properties=None):
327 get_rspline(targets,'-TP')
328 sources += bjam.call('get-target-variable',targets,'PCH_FILE')
329 sources += bjam.call('get-target-variable',targets,'PCH_HEADER')
330 preprocess_c_cpp(targets,sources)
332 def compile_cpp_pch(targets,sources=[],properties=None):
333 get_rspline([targets[1]], '-TP')
334 get_rspline([targets[2]], '-TP')
335 pch_source = bjam.call('get-target-variable', targets, 'PCH_SOURCE')
336 sources += pch_source
338 get_manager().engine().set_update_action('compile-c-c++-pch-s', targets, sources, properties)
339 get_manager().engine().add_dependency(targets,pch_source)
340 compile_c_cpp_pch_s(targets,sources)
342 get_manager().engine().set_update_action('compile-c-c++-pch', targets, sources, properties)
343 compile_c_cpp_pch(targets,sources)
346 # Action for running the C/C++ compiler without using precompiled headers.
348 # WARNING: Synchronize any changes this in action with intel-win
350 # Notes regarding PDB generation, for when we use <debug-symbols>on/<debug-store>database
352 # 1. PDB_CFLAG is only set for <debug-symbols>on/<debug-store>database, ensuring that the /Fd flag is dropped if PDB_CFLAG is empty
354 # 2. When compiling executables's source files, PDB_NAME is set on a per-source file basis by rule compile-c-c++.
355 # The linker will pull these into the executable's PDB
357 # 3. When compiling library's source files, PDB_NAME is updated to <libname>.pdb for each source file by rule archive,
358 # as in this case the compiler must be used to create a single PDB for our library.
361 compile_action = '$(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER)'
362 engine.register_action(
366 bound_list=['PDB_NAME'])
368 engine.register_action(
371 function=compile_cpp,
372 bound_list=['PDB_NAME'])
375 preprocess_action = '$(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)"'
377 engine.register_action(
380 function=compile_c_preprocess,
381 bound_list=['PDB_NAME'])
383 engine.register_action(
384 'msvc.preprocess.c++',
386 function=compile_cpp_preprocess,
387 bound_list=['PDB_NAME'])
389 def compile_c_cpp(targets,sources=None):
390 pch_header = bjam.call('get-target-variable',targets[0],'PCH_HEADER')
391 pch_file = bjam.call('get-target-variable',targets[0],'PCH_FILE')
392 if pch_header: get_manager().engine().add_dependency(targets[0],pch_header)
393 if pch_file: get_manager().engine().add_dependency(targets[0],pch_file)
394 bjam.call('set-target-variable',targets,'PDB_NAME', os.path.splitext(targets[0])[0] + '.pdb')
396 def preprocess_c_cpp(targets,sources=None):
398 return compile_c_cpp(targets,sources)
400 # Action for running the C/C++ compiler using precompiled headers. In addition
401 # to whatever else it needs to compile, this action also adds a temporary source
402 # .cpp file used to compile the precompiled headers themselves.
404 engine.register_action(
405 'msvc.compile.c.pch',
406 None, # action set by the function
407 function=compile_c_pch)
409 engine.register_action(
410 'msvc.compile.c++.pch',
411 None, # action set by the function
412 function=compile_cpp_pch)
415 # See midl.py for details.
417 engine.register_action(
419 '''$(.IDL) /nologo @"@($(<[1]:W).rsp:E=
429 /dlldata "$(<[5]:W)")"
431 {touch} "$(<[5]:W)"'''.format(touch=common.file_creation_command()))
433 engine.register_action(
435 '$(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"')
437 engine.register_action(
439 '$(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)"')
441 def link_dll(targets,sources=None,properties=None):
442 get_manager().engine().add_dependency(targets,bjam.call('get-target-variable',targets,'DEF_FILE'))
443 manifest(targets, sources, properties)
445 def manifest(targets,sources=None,properties=None):
446 if 'on' in properties.get('<embed-manifest>'):
447 get_manager().engine().set_update_action('msvc.manifest', targets, sources, properties)
450 # Incremental linking a DLL causes no end of problems: if the actual exports do
451 # not change, the import .lib file is never updated. Therefore, the .lib is
452 # always out-of-date and gets rebuilt every time. I am not sure that incremental
453 # linking is such a great idea in general, but in this case I am sure we do not
456 # Windows manifest is a new way to specify dependencies on managed DotNet
457 # assemblies and Windows native DLLs. The manifests are embedded as resources
458 # and are useful in any PE target (both DLL and EXE).
461 engine.register_action(
463 '''$(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
465 $(LIBRARIES_MENTIONED_BY_FILE)
467 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
468 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
469 if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%''',
471 bound_list=['PDB_NAME','DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
473 engine.register_action(
475 '''if exist "$(<[1]).manifest" (
476 $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
479 engine.register_action(
481 '''$(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
483 $(LIBRARIES_MENTIONED_BY_FILE)
485 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
486 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
487 if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%''',
489 bound_list=['DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
491 engine.register_action(
493 '''if exist "$(<[1]).manifest" (
494 $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
497 engine.register_action(
499 '''$(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
501 $(LIBRARIES_MENTIONED_BY_FILE)
503 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
504 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
506 bound_list=['PDB_NAME','DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
508 engine.register_action(
510 '''if test -e "$(<[1]).manifest"; then
511 $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
514 engine.register_action(
516 '''$(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
518 $(LIBRARIES_MENTIONED_BY_FILE)
520 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
521 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
523 bound_list=['DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
525 engine.register_action(
527 '''if test -e "$(<[1]).manifest"; then
528 $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
532 ################################################################################
536 ################################################################################
538 class MsvcPchGenerator(pch.PchGenerator):
540 # Inherit the __init__ method
542 def run_pch(self, project, name, prop_set, sources):
543 # Find the header in sources. Ignore any CPP sources.
547 if type.is_derived(s.type(), 'H'):
549 elif type.is_derived(s.type(), 'CPP') or type.is_derived(s.type(), 'C'):
553 raise RuntimeError( "can not build pch without pch-header" )
555 # If we do not have the PCH source - that is fine. We will just create a
556 # temporary .cpp file in the action.
557 temp_prop_set = property_set.create([Property('pch-source',pch_source)]+prop_set.all())
558 generated = Generator.run(project,name,temp_prop_set,pch_header)
561 if type.is_derived(g.type(), 'PCH'):
563 return property_set.create([Property('pch-header',pch_header),Property('pch-file',pch_file)]+generated)
566 ################################################################################
570 ################################################################################
572 # Detects versions listed as '_known_versions' by checking registry information,
573 # environment variables & default paths. Supports both native Windows and
575 def auto_detect_toolset_versions():
576 if on_windows() or on_cygwin():
577 for version in _known_versions:
578 versionVarName = '__version_{}_reg'.format(version.replace('.','_'))
579 if versionVarName in globals():
581 for x in [ '', 'Wow6432Node\\' ]:
583 with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\{}{}'.format(x, globals()[versionVarName])) as reg_key:
584 vc_path = _winreg.QueryValueEx(reg_key, "ProductDir")[0]
588 vc_path = os.path.join(vc_path,'bin')
589 register_configuration(version,os.path.normpath(vc_path))
591 for i in _known_versions:
592 if not i in __versions.all():
593 register_configuration(i,default_path(i))
596 # Worker rule for toolset version configuration. Takes an explicit version id or
597 # nothing in case it should configure the default toolset version (the first
598 # registered one or a new 'default' one in case no toolset versions have been
602 def configure_really(version=None, options=[]):
605 # Take the first registered (i.e. auto-detected) version.
606 version = __versions.first()
609 # Note: 'version' can still be empty at this point if no versions have
610 # been auto-detected.
614 # Version alias -> real version number.
615 version = globals().get("__version_alias_{}".format(version), version)
617 # Check whether the selected configuration is already in use.
618 if version in __versions.used():
619 # Allow multiple 'toolset.using' calls for the same configuration if the
620 # identical sets of options are used.
621 if options and options != __versions.get(version,'options'):
622 raise RuntimeError("MSVC toolset configuration: Toolset version '$(version)' already configured.".format(version))
624 # Register a new configuration.
625 __versions.register(version)
627 # Add user-supplied to auto-detected options.
628 version_opts = __versions.get(version, 'options')
630 options = version_opts + options
632 # Mark the configuration as 'used'.
633 __versions.use(version)
634 # Generate conditions and save them.
635 conditions = common.check_init_parameters('msvc', None, ('version', v))
636 __versions.set(version, 'conditions', conditions)
637 command = feature.get_values('<command>', options)
639 # If version is specified, we try to search first in default paths, and
641 command = common.get_invocation_command('msvc', 'cl.exe', command, default_paths(version))
642 common.handle_options('msvc', conditions, command, options)
645 # Even if version is not explicitly specified, try to detect the
646 # version from the path.
647 # FIXME: We currently detect both Microsoft Visual Studio 9.0 and
648 # 9.0express as 9.0 here.
649 if re.search("Microsoft Visual Studio 11", command):
651 if re.search("Microsoft Visual Studio 10", command):
653 elif re.search("Microsoft Visual Studio 9", command):
655 elif re.search("Microsoft Visual Studio 8", command):
657 elif re.search("NET 2003[\/\\]VC7", command):
659 elif re.search("Microsoft Visual C\\+\\+ Toolkit 2003", command):
660 version = '7.1toolkit'
661 elif re.search(".NET[\/\\]VC7", command):
666 # Generate and register setup command.
668 below_8_0 = re.search("^[67]\\.",version) != None
673 cpu = ['i386', 'amd64', 'ia64']
678 # TODO: Note that if we specify a non-existant toolset version then
679 # this rule may find and use a corresponding compiler executable
680 # belonging to an incorrect toolset version. For example, if you
681 # have only MSVC 7.1 installed, have its executable on the path and
682 # specify you want Boost Build to use MSVC 9.0, then you want Boost
683 # Build to report an error but this may cause it to silently use the
684 # MSVC 7.1 compiler even though it thinks it is using the msvc-9.0
686 command = common.get_absolute_tool_path(command)
689 parent = os.path.dirname(os.path.normpath(command))
690 # Setup will be used if the command name has been specified. If
691 # setup is not specified explicitly then a default setup script will
692 # be used instead. Setup scripts may be global or arhitecture/
693 # /platform/cpu specific. Setup options are used only in case of
694 # global setup scripts.
696 # Default setup scripts provided with different VC distributions:
698 # VC 7.1 had only the vcvars32.bat script specific to 32 bit i386
699 # builds. It was located in the bin folder for the regular version
700 # and in the root folder for the free VC 7.1 tools.
702 # Later 8.0 & 9.0 versions introduce separate platform specific
703 # vcvars*.bat scripts (e.g. 32 bit, 64 bit AMD or 64 bit Itanium)
704 # located in or under the bin folder. Most also include a global
705 # vcvarsall.bat helper script located in the root folder which runs
706 # one of the aforementioned vcvars*.bat scripts based on the options
707 # passed to it. So far only the version coming with some PlatformSDK
708 # distributions does not include this top level script but to
709 # support those we need to fall back to using the worker scripts
710 # directly in case the top level script can not be found.
712 global_setup = feature.get_values('<setup>',options)
714 global_setup = global_setup[0]
718 if not below_8_0 and not global_setup:
719 global_setup = locate_default_setup(command,parent,'vcvarsall.bat')
723 'amd64' : 'vcvarsx86_amd64.bat',
724 'i386' : 'vcvars32.bat',
725 'ia64' : 'vcvarsx86_ia64.bat' }
727 # http://msdn2.microsoft.com/en-us/library/x4d2c09s(VS.80).aspx and
728 # http://msdn2.microsoft.com/en-us/library/x4d2c09s(vs.90).aspx
729 # mention an x86_IPF option, that seems to be a documentation bug
730 # and x86_ia64 is the correct option.
731 default_global_setup_options = {
732 'amd64' : 'x86_amd64',
734 'ia64' : 'x86_ia64' }
736 somehow_detect_the_itanium_platform = None
737 # When using 64-bit Windows, and targeting 64-bit, it is possible to
738 # use a native 64-bit compiler, selected by the "amd64" & "ia64"
739 # parameters to vcvarsall.bat. There are two variables we can use --
740 # PROCESSOR_ARCHITECTURE and PROCESSOR_IDENTIFIER. The first is
741 # 'x86' when running 32-bit Windows, no matter which processor is
742 # used, and 'AMD64' on 64-bit windows on x86 (either AMD64 or EM64T)
745 if re.search( 'AMD64', environ[ "PROCESSOR_ARCHITECTURE" ] ) != None:
746 default_global_setup_options[ 'amd64' ] = 'amd64'
747 # TODO: The same 'native compiler usage' should be implemented for
748 # the Itanium platform by using the "ia64" parameter. For this
749 # though we need someone with access to this platform who can find
750 # out how to correctly detect this case.
751 elif somehow_detect_the_itanium_platform:
752 default_global_setup_options[ 'ia64' ] = 'ia64'
754 setup_prefix = "call "
755 setup_suffix = """ >nul\n"""
757 setup_prefix = "cmd.exe /S /C call "
758 setup_suffix = " \">nul\" \"&&\" "
762 setup_cpu = feature.get_values('<setup-{}>'.format(c),options)
766 setup_cpu = global_setup
767 # If needed we can easily add using configuration flags
768 # here for overriding which options get passed to the
769 # global setup command for which target platform:
770 # setup_options = feature.get_values('<setup-options-{}>'.format(c),options)
771 if not setup_options:
772 setup_options = default_global_setup_options[ c ]
774 setup_cpu = locate_default_setup(command, parent, default_setup[ c ])
776 # Cygwin to Windows path translation.
777 # setup-$(c) = "\""$(setup-$(c):W)"\"" ;
779 # Append setup options to the setup name and add the final setup
781 setup_scripts[ c ] = '{}"{}" {}{}'.format(setup_prefix, setup_cpu, setup_options, setup_suffix)
783 # Get tool names (if any) and finish setup.
784 compiler = feature.get_values("<compiler>", options)
788 linker = feature.get_values("<linker>", options)
792 resource_compiler = feature.get_values("<resource-compiler>", options)
793 if not resource_compiler:
794 resource_compiler = "rc"
796 # Turn on some options for i386 assembler
797 # -coff generate COFF format object file (compatible with cl.exe output)
798 default_assembler_amd64 = 'ml64'
799 default_assembler_i386 = 'ml -coff'
800 default_assembler_ia64 = 'ias'
802 assembler = feature.get_values('<assembler>',options)
804 idl_compiler = feature.get_values('<idl-compiler>',options)
806 idl_compiler = 'midl'
808 mc_compiler = feature.get_values('<mc-compiler>',options)
812 manifest_tool = feature.get_values('<manifest-tool>',options)
813 if not manifest_tool:
816 cc_filter = feature.get_values('<compiler-filter>',options)
819 cpu_conditions = [ condition + '/' + arch for arch in globals()['__cpu_arch_{}'.format(c)] for condition in conditions ]
821 setup_script = setup_scripts.get(c, '')
824 for cpu_condition in cpu_conditions:
825 print "notice: [msvc-cfg] condition: '{}', setup: '{}'".format(cpu_condition,setup_script)
827 cpu_assembler = assembler
828 if not cpu_assembler:
829 cpu_assembler = locals()['default_assembler_{}'.format(c)]
831 toolset.flags('msvc.compile', '.CC' , cpu_conditions, ['{}{} /Zm800 -nologo' .format(setup_script, compiler)])
832 toolset.flags('msvc.compile', '.RC' , cpu_conditions, ['{}{} -nologo' .format(setup_script, resource_compiler)])
833 toolset.flags('msvc.compile', '.ASM', cpu_conditions, ['{}{} ' .format(setup_script, cpu_assembler)])
834 toolset.flags('msvc.link' , '.LD' , cpu_conditions, ['{}{} /NOLOGO /INCREMENTAL:NO'.format(setup_script, linker)])
835 toolset.flags('msvc.archive', '.LD' , cpu_conditions, ['{}{} /lib /NOLOGO' .format(setup_script, linker)])
836 toolset.flags('msvc.compile', '.IDL', cpu_conditions, ['{}{} ' .format(setup_script, idl_compiler)])
837 toolset.flags('msvc.compile', '.MC' , cpu_conditions, ['{}{} ' .format(setup_script, mc_compiler)])
838 toolset.flags('msvc.link' , '.MT' , cpu_conditions, ['{}{} -nologo' .format(setup_script, manifest_tool)])
841 toolset.flags('msvc', '.CC.FILTER', cpu_conditions, ['"|" {}'.format(cc_filter)])
843 # Set version-specific flags.
844 configure_version_specific('msvc', version, conditions)
847 # Returns the default installation path for the given version.
849 def default_path(version):
850 # Use auto-detected path if possible.
851 options = __versions.get(version, 'options')
854 tmp_path = feature.get_values('<command>', options)
857 tmp_path="".join(tmp_path)
858 tmp_path=os.path.dirname(tmp_path)
860 env_var_var_name = '__version_{}_env'.format(version.replace('.','_'))
862 if env_var_var_name in globals():
863 env_var_name = globals()[env_var_var_name]
864 if env_var_name in os.environ:
865 vc_path = environ[env_var_name]
867 vc_path = os.path.join(vc_path,globals()['__version_{}_envpath'.format(version.replace('.','_'))])
868 tmp_path = os.path.normpath(vc_path)
870 var_name = '__version_{}_path'.format(version.replace('.','_'))
871 if not tmp_path and var_name in globals():
872 tmp_path = os.path.normpath(os.path.join(common.get_program_files_dir(), globals()[var_name]))
876 # Returns either the default installation path (if 'version' is not empty) or
877 # list of all known default paths (if no version is given)
879 def default_paths(version = None):
882 path = default_path(version)
884 possible_paths.append(path)
886 for i in _known_versions:
887 path = default_path(i)
889 possible_paths.append(path)
890 return possible_paths
893 class MsvcLinkingGenerator(builtin.LinkingGenerator):
894 # Calls the base version. If necessary, also create a target for the
895 # manifest file.specifying source's name as the name of the created
896 # target. As result, the PCH will be named whatever.hpp.gch, and not
898 def generated_targets(self, sources, prop_set, project, name):
899 result = builtin.LinkingGenerator.generated_targets(self, sources, prop_set, project, name)
901 name_main = result[0].name()
902 action = result[0].action()
904 if prop_set.get('<debug-symbols>') == 'on':
905 # We force exact name on PDB. The reason is tagging -- the tag rule may
906 # reasonably special case some target types, like SHARED_LIB. The tag rule
907 # will not catch PDB, and it cannot even easily figure if PDB is paired with
908 # SHARED_LIB or EXE or something else. Because PDB always get the
909 # same name as the main target, with .pdb as extension, just force it.
910 target = FileTarget(name_main.split_ext()[0]+'.pdb','PDB',project,action,True)
911 registered_target = virtual_target.register(target)
912 if target != registered_target:
913 action.replace_targets(target,registered_target)
914 result.append(registered_target)
915 if prop_set.get('<embed-manifest>') == 'off':
916 # Manifest is evil target. It has .manifest appened to the name of
917 # main target, including extension. E.g. a.exe.manifest. We use 'exact'
918 # name because to achieve this effect.
919 target = FileTarget(name_main+'.manifest', 'MANIFEST', project, action, True)
920 registered_target = virtual_target.register(target)
921 if target != registered_target:
922 action.replace_targets(target,registered_target)
923 result.append(registered_target)
927 # Unsafe worker rule for the register-toolset() rule. Must not be called
930 def register_toolset_really():
931 feature.extend('toolset', ['msvc'])
933 # Intel and msvc supposedly have link-compatible objects.
934 feature.subfeature( 'toolset', 'msvc', 'vendor', 'intel', ['propagated', 'optional'])
936 # Inherit MIDL flags.
937 toolset.inherit_flags('msvc', 'midl')
940 toolset.inherit_flags('msvc','mc')
942 # Dynamic runtime comes only in MT flavour.
943 toolset.add_requirements(['<toolset>msvc,<runtime-link>shared:<threading>multi'])
945 # Declare msvc toolset specific features.
946 feature.feature('debug-store', ['object', 'database'], ['propagated'])
947 feature.feature('pch-source', [], ['dependency', 'free'])
949 # Declare generators.
951 # TODO: Is it possible to combine these? Make the generators
952 # non-composing so that they do not convert each source into a separate
954 generators.register(MsvcLinkingGenerator('msvc.link', True, ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ['EXE'], ['<toolset>msvc']))
955 generators.register(MsvcLinkingGenerator('msvc.link.dll', True, ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'], ['SHARED_LIB','IMPORT_LIB'], ['<toolset>msvc']))
957 builtin.register_archiver('msvc.archive', ['OBJ'], ['STATIC_LIB'], ['<toolset>msvc'])
958 builtin.register_c_compiler('msvc.compile.c++', ['CPP'], ['OBJ'], ['<toolset>msvc'])
959 builtin.register_c_compiler('msvc.compile.c', ['C'], ['OBJ'], ['<toolset>msvc'])
960 builtin.register_c_compiler('msvc.compile.c++.preprocess', ['CPP'], ['PREPROCESSED_CPP'], ['<toolset>msvc'])
961 builtin.register_c_compiler('msvc.compile.c.preprocess', ['C'], ['PREPROCESSED_C'], ['<toolset>msvc'])
963 # Using 'register-c-compiler' adds the build directory to INCLUDES.
964 builtin.register_c_compiler('msvc.compile.rc', ['RC'], ['OBJ(%_res)'], ['<toolset>msvc'])
965 generators.override('msvc.compile.rc', 'rc.compile.resource')
966 generators.register_standard('msvc.compile.asm', ['ASM'], ['OBJ'], ['<toolset>msvc'])
968 builtin.register_c_compiler('msvc.compile.idl', ['IDL'], ['MSTYPELIB', 'H', 'C(%_i)', 'C(%_proxy)', 'C(%_dlldata)'], ['<toolset>msvc'])
969 generators.override('msvc.compile.idl', 'midl.compile.idl')
971 generators.register_standard('msvc.compile.mc', ['MC'], ['H','RC'], ['<toolset>msvc'])
972 generators.override('msvc.compile.mc', 'mc.compile')
974 # Note: the 'H' source type will catch both '.h' and '.hpp' headers as
975 # the latter have their HPP type derived from H. The type of compilation
976 # is determined entirely by the destination type.
977 generators.register(MsvcPchGenerator('msvc.compile.c.pch', False, ['H'], ['C_PCH','OBJ'], ['<pch>on', '<toolset>msvc']))
978 generators.register(MsvcPchGenerator('msvc.compile.c++.pch', False, ['H'], ['CPP_PCH','OBJ'], ['<pch>on', '<toolset>msvc']))
980 generators.override('msvc.compile.c.pch', 'pch.default-c-pch-generator')
981 generators.override('msvc.compile.c++.pch', 'pch.default-cpp-pch-generator')
983 toolset.flags('msvc.compile', 'PCH_FILE' , ['<pch>on'], ['<pch-file>' ])
984 toolset.flags('msvc.compile', 'PCH_SOURCE', ['<pch>on'], ['<pch-source>'])
985 toolset.flags('msvc.compile', 'PCH_HEADER', ['<pch>on'], ['<pch-header>'])
988 # Declare flags for compilation.
990 toolset.flags('msvc.compile', 'CFLAGS', ['<optimization>speed'], ['/O2'])
991 toolset.flags('msvc.compile', 'CFLAGS', ['<optimization>space'], ['/O1'])
993 toolset.flags('msvc.compile', 'CFLAGS', [ a + '/<instruction-set>' + t for a in __cpu_arch_ia64 for t in __cpu_type_itanium ], ['/G1'])
994 toolset.flags('msvc.compile', 'CFLAGS', [ a + '/<instruction-set>' + t for a in __cpu_arch_ia64 for t in __cpu_type_itanium2 ], ['/G2'])
996 toolset.flags('msvc.compile', 'CFLAGS', ['<debug-symbols>on/<debug-store>object'], ['/Z7'])
997 toolset.flags('msvc.compile', 'CFLAGS', ['<debug-symbols>on/<debug-store>database'], ['/Zi'])
998 toolset.flags('msvc.compile', 'CFLAGS', ['<optimization>off'], ['/Od'])
999 toolset.flags('msvc.compile', 'CFLAGS', ['<inlining>off'], ['/Ob0'])
1000 toolset.flags('msvc.compile', 'CFLAGS', ['<inlining>on'], ['/Ob1'])
1001 toolset.flags('msvc.compile', 'CFLAGS', ['<inlining>full'], ['/Ob2'])
1003 toolset.flags('msvc.compile', 'CFLAGS', ['<warnings>on'], ['/W3'])
1004 toolset.flags('msvc.compile', 'CFLAGS', ['<warnings>off'], ['/W0'])
1005 toolset.flags('msvc.compile', 'CFLAGS', ['<warnings>all'], ['/W4'])
1006 toolset.flags('msvc.compile', 'CFLAGS', ['<warnings-as-errors>on'], ['/WX'])
1008 toolset.flags('msvc.compile', 'C++FLAGS', ['<exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>off'], ['/EHs'])
1009 toolset.flags('msvc.compile', 'C++FLAGS', ['<exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>on'], ['/EHsc'])
1010 toolset.flags('msvc.compile', 'C++FLAGS', ['<exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>off'], ['/EHa'])
1011 toolset.flags('msvc.compile', 'C++FLAGS', ['<exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>on'], ['/EHac'])
1013 # By default 8.0 enables rtti support while prior versions disabled it. We
1014 # simply enable or disable it explicitly so we do not have to depend on this
1015 # default behaviour.
1016 toolset.flags('msvc.compile', 'CFLAGS', ['<rtti>on'], ['/GR'])
1017 toolset.flags('msvc.compile', 'CFLAGS', ['<rtti>off'], ['/GR-'])
1018 toolset.flags('msvc.compile', 'CFLAGS', ['<runtime-debugging>off/<runtime-link>shared'], ['/MD'])
1019 toolset.flags('msvc.compile', 'CFLAGS', ['<runtime-debugging>on/<runtime-link>shared'], ['/MDd'])
1021 toolset.flags('msvc.compile', 'CFLAGS', ['<runtime-debugging>off/<runtime-link>static/<threading>multi'], ['/MT'])
1022 toolset.flags('msvc.compile', 'CFLAGS', ['<runtime-debugging>on/<runtime-link>static/<threading>multi'], ['/MTd'])
1024 toolset.flags('msvc.compile', 'OPTIONS', [], ['<cflags>'])
1025 toolset.flags('msvc.compile.c++', 'OPTIONS', [], ['<cxxflags>'])
1027 toolset.flags('msvc.compile', 'PDB_CFLAG', ['<debug-symbols>on/<debug-store>database'],['/Fd'])
1029 toolset.flags('msvc.compile', 'DEFINES', [], ['<define>'])
1030 toolset.flags('msvc.compile', 'UNDEFS', [], ['<undef>'])
1031 toolset.flags('msvc.compile', 'INCLUDES', [], ['<include>'])
1033 # Declare flags for the assembler.
1034 toolset.flags('msvc.compile.asm', 'USER_ASMFLAGS', [], ['<asmflags>'])
1036 toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<debug-symbols>on'], ['/Zi', '/Zd'])
1038 toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<warnings>on'], ['/W3'])
1039 toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<warnings>off'], ['/W0'])
1040 toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<warnings>all'], ['/W4'])
1041 toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<warnings-as-errors>on'], ['/WX'])
1043 toolset.flags('msvc.compile.asm', 'DEFINES', [], ['<define>'])
1045 # Declare flags for linking.
1046 toolset.flags('msvc.link', 'PDB_LINKFLAG', ['<debug-symbols>on/<debug-store>database'], ['/PDB']) # not used yet
1047 toolset.flags('msvc.link', 'LINKFLAGS', ['<debug-symbols>on'], ['/DEBUG'])
1048 toolset.flags('msvc.link', 'DEF_FILE', [], ['<def-file>'])
1050 # The linker disables the default optimizations when using /DEBUG so we
1051 # have to enable them manually for release builds with debug symbols.
1052 toolset.flags('msvc', 'LINKFLAGS', ['<debug-symbols>on/<runtime-debugging>off'], ['/OPT:REF,ICF'])
1054 toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>console'], ['/subsystem:console'])
1055 toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>gui'], ['/subsystem:windows'])
1056 toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>wince'], ['/subsystem:windowsce'])
1057 toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>native'], ['/subsystem:native'])
1058 toolset.flags('msvc', 'LINKFLAGS', ['<user-interface>auto'], ['/subsystem:posix'])
1060 toolset.flags('msvc.link', 'OPTIONS', [], ['<linkflags>'])
1061 toolset.flags('msvc.link', 'LINKPATH', [], ['<library-path>'])
1063 toolset.flags('msvc.link', 'FINDLIBS_ST', ['<find-static-library>'])
1064 toolset.flags('msvc.link', 'FINDLIBS_SA', ['<find-shared-library>'])
1065 toolset.flags('msvc.link', 'LIBRARY_OPTION', ['<toolset>msvc'])
1066 toolset.flags('msvc.link', 'LIBRARIES_MENTIONED_BY_FILE', ['<library-file>'])
1068 toolset.flags('msvc.archive', 'AROPTIONS', [], ['<archiveflags>'])
1071 # Locates the requested setup script under the given folder and returns its full
1072 # path or nothing in case the script can not be found. In case multiple scripts
1073 # are found only the first one is returned.
1075 # TODO: There used to exist a code comment for the msvc.init rule stating that
1076 # we do not correctly detect the location of the vcvars32.bat setup script for
1077 # the free VC7.1 tools in case user explicitly provides a path. This should be
1078 # tested or simply remove this whole comment in case this toolset version is no
1081 def locate_default_setup(command, parent, setup_name):
1082 for setup in [os.path.join(dir,setup_name) for dir in [command,parent]]:
1083 if os.path.exists(setup):
1088 # Validates given path, registers found configuration and prints debug
1089 # information about it.
1091 def register_configuration(version, path=None):
1093 command = os.path.join(path, 'cl.exe')
1094 if os.path.exists(command):
1096 print "notice: [msvc-cfg] msvc-$(version) detected, command: ''".format(version,command)
1097 __versions.register(version)
1098 __versions.set(version,'options',['<command>{}'.format(command)])
1101 ################################################################################
1103 # Startup code executed when loading this module.
1105 ################################################################################
1107 # Similar to Configurations, but remembers the first registered configuration.
1108 class MSVCConfigurations(Configurations):
1110 Configurations.__init__(self)
1113 def register(self, id):
1114 Configurations.register(self,id)
1122 # List of all registered configurations.
1123 __versions = MSVCConfigurations()
1125 # Supported CPU architectures.
1127 '<architecture>/<address-model>',
1128 '<architecture>/<address-model>32',
1129 '<architecture>x86/<address-model>',
1130 '<architecture>x86/<address-model>32']
1132 __cpu_arch_amd64 = [
1133 '<architecture>/<address-model>64',
1134 '<architecture>x86/<address-model>64']
1137 '<architecture>ia64/<address-model>',
1138 '<architecture>ia64/<address-model>64']
1141 # Supported CPU types (only Itanium optimization options are supported from
1142 # VC++ 2005 on). See
1143 # http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx for more
1144 # detailed information.
1145 __cpu_type_g5 = ['i586', 'pentium', 'pentium-mmx' ]
1146 __cpu_type_g6 = ['i686', 'pentiumpro', 'pentium2', 'pentium3', 'pentium3m', 'pentium-m', 'k6',
1147 'k6-2', 'k6-3', 'winchip-c6', 'winchip2', 'c3', 'c3-2' ]
1148 __cpu_type_em64t = ['prescott', 'nocona', 'conroe', 'conroe-xe', 'conroe-l', 'allendale', 'mermon',
1149 'mermon-xe', 'kentsfield', 'kentsfield-xe', 'penryn', 'wolfdale',
1150 'yorksfield', 'nehalem' ]
1151 __cpu_type_amd64 = ['k8', 'opteron', 'athlon64', 'athlon-fx']
1152 __cpu_type_g7 = ['pentium4', 'pentium4m', 'athlon', 'athlon-tbird', 'athlon-4', 'athlon-xp'
1153 'athlon-mp'] + __cpu_type_em64t + __cpu_type_amd64
1154 __cpu_type_itanium = ['itanium', 'itanium1', 'merced']
1155 __cpu_type_itanium2 = ['itanium2', 'mckinley']
1158 # Known toolset versions, in order of preference.
1159 _known_versions = ['11.0', '10.0', '10.0express', '9.0', '9.0express', '8.0', '8.0express', '7.1', '7.1toolkit', '7.0', '6.0']
1162 __version_alias_6 = '6.0'
1163 __version_alias_6_5 = '6.0'
1164 __version_alias_7 = '7.0'
1165 __version_alias_8 = '8.0'
1166 __version_alias_9 = '9.0'
1167 __version_alias_10 = '10.0'
1168 __version_alias_11 = '11.0'
1170 # Names of registry keys containing the Visual C++ installation path (relative
1171 # to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
1172 __version_6_0_reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++"
1173 __version_7_0_reg = "VisualStudio\\7.0\\Setup\\VC"
1174 __version_7_1_reg = "VisualStudio\\7.1\\Setup\\VC"
1175 __version_8_0_reg = "VisualStudio\\8.0\\Setup\\VC"
1176 __version_8_0express_reg = "VCExpress\\8.0\\Setup\\VC"
1177 __version_9_0_reg = "VisualStudio\\9.0\\Setup\\VC"
1178 __version_9_0express_reg = "VCExpress\\9.0\\Setup\\VC"
1179 __version_10_0_reg = "VisualStudio\\10.0\\Setup\\VC"
1180 __version_10_0express_reg = "VCExpress\\10.0\\Setup\\VC"
1181 __version_11_0_reg = "VisualStudio\\11.0\\Setup\\VC"
1183 # Visual C++ Toolkit 2003 does not store its installation path in the registry.
1184 # The environment variable 'VCToolkitInstallDir' and the default installation
1185 # path will be checked instead.
1186 __version_7_1toolkit_path = 'Microsoft Visual C++ Toolkit 2003\\bin'
1187 __version_7_1toolkit_env = 'VCToolkitInstallDir'
1189 # Path to the folder containing "cl.exe" relative to the value of the
1190 # corresponding environment variable.
1191 __version_7_1toolkit_envpath = 'bin' ;
1194 # Auto-detect all the available msvc installations on the system.
1195 auto_detect_toolset_versions()
1197 # And finally trigger the actual Boost Build toolset registration.