Imported Upstream version 1.51.0
[platform/upstream/boost.git] / tools / build / v2 / tools / msvc.py
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
9 #
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)
13
14 ################################################################################
15 #
16 # MSVC Boost Build toolset module.
17 # --------------------------------
18 #
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.
22 #
23 ################################################################################
24
25 from os import environ
26 import os.path
27 import re
28 import _winreg
29
30 import bjam
31
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
41
42 __debug = None
43
44 def debug():
45     global __debug
46     if __debug is None:
47         __debug = "--debug-configuration" in bjam.variable("ARGV")        
48     return __debug
49
50
51 # It is not yet clear what to do with Cygwin on python port.    
52 def on_cygwin():
53     return False
54
55     
56 type.register('MANIFEST', ['manifest'])
57 feature.feature('embed-manifest',['on','off'], ['incidental', 'propagated']) ;
58
59 type.register('PDB',['pdb'])
60
61 ################################################################################
62 #
63 # Public rules.
64 #
65 ################################################################################
66
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:
70 #
71 #    using msvc : 6.5 : cl.exe ;
72 #    using msvc : 7.0 : Y:/foo/bar/cl.exe ;
73 #
74 # The version parameter may be ommited:
75 #
76 #    using msvc : : Z:/foo/bar/cl.exe ;
77 #
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.
82 #
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:
86 #
87 #                                      Nothing            "x.y"
88 # Passed   Nothing       "x.y"         detected,          detected,
89 # version  detected      detected      cl.exe in path     cl.exe in path
90 #
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"
95 #
96 # "x.y" - refers to a detected version;
97 # "a.b" - refers to an undetected version.
98 #
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.
102
103 def init(version = None, command = None, options = None):
104     # When initialized from
105     # using msvc : x.0 ;
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:
112         version = version[0]
113
114     options = to_seq(options)
115     command = to_seq(command)
116     
117     if command:
118         options.append("<command>"+command)
119     configure(version,options)
120
121 def configure(version=None, options=None):
122     if version == "all":
123         if options:
124             raise RuntimeError("MSVC toolset configuration: options should be empty when '{}' is specified.".format(version))
125         
126         # Configure (i.e. mark as used) all registered versions.
127         all_versions = __versions.all()
128         if not all_versions:
129             if debug():
130                 print "notice: [msvc-cfg] Asked to configure all registered" \
131                       "msvc toolset versions when there are none currently" \
132                       "registered." ;
133         else:
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.
140                 configure_really(v)
141     elif version == "default":
142         configure_really(None,options)
143     else:
144         configure_really(version, options)
145
146 def extend_conditions(conditions,exts):
147     return [ cond + '/' + ext for cond in conditions for ext in exts ]
148         
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'])
158
159         # Explicitly disable the 'function is deprecated' warning. Some msvc
160         # versions have a bug, causing them to emit the deprecation warning even
161         # with /W0.
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'])
167
168     #
169     # Processor-specific optimization.
170     #
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'])
176
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'])
181
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'])
185
186         # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math"
187         # tests will fail.
188         toolset.flags('{}.compile'.format(toolset_arg), 'CFLAGS', conditions, ['/Op'])
189
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'])
193     else:
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'])
196
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'])
199
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'])
203
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'])
208         
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'])
212
213
214 # Registers this toolset including all of its flags, features & generators. Does
215 # nothing on repeated calls.
216
217 def register_toolset():
218      if not 'msvc' in feature.values('toolset'):
219         register_toolset_really()
220         
221     
222 engine = get_manager().engine()
223
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
227 #
228 # Poking at source targets this way is probably not clean, but it's the
229 # easiest approach.
230 def archive(targets, sources=None, properties=None):
231     bjam.call('set-target-variable',targets,'PDB_NAME', os.path.splitext(targets[0])[0] + '.pdb')
232
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.
236 if not on_cygwin():
237     engine.register_action(
238         'msvc.archive',
239         '''if exist "$(<[1])" DEL "$(<[1])"
240         $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=
241 "$(>)"
242 $(LIBRARIES_MENTIONED_BY_FILE)
243 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
244 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
245     function=archive)
246 else:
247     engine.register_action(
248         'msvc.archive',
249         '''{rm} "$(<[1])"
250            $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=
251 "$(>)"
252 $(LIBRARIES_MENTIONED_BY_FILE)
253 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
254 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"'''.format(rm=common.rm_command()),
255         function=archive)
256         
257 # For the assembler the following options are turned on by default:
258 #
259 #   -Zp4   align structures to 4 bytes
260 #   -Cp    preserve case of user identifiers
261 #   -Cx    preserve case in publics, externs
262 #
263 engine.register_action(
264     'msvc.compile.asm',
265     '$(.ASM) -c -Zp4 -Cp -Cx -D$(DEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) -Fo "$(<:W)" "$(>:W)"' )
266
267
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 ])
272
273
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)'''
279     
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)
289
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)
296
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)
303
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
310     if 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)
314     else:
315         get_manager().engine().set_update_action('compile-c-c++-pch', targets, sources, properties)
316         compile_c_cpp_pch(targets,sources)
317
318 toolset.flags( 'msvc', 'YLOPTION', [], ['-Yl'] )
319
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)
325
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)
331
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
337     if 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)
341     else:
342         get_manager().engine().set_update_action('compile-c-c++-pch', targets, sources, properties)
343         compile_c_cpp_pch(targets,sources)
344
345
346 # Action for running the C/C++ compiler without using precompiled headers.
347 #
348 # WARNING: Synchronize any changes this in action with intel-win
349 #
350 # Notes regarding PDB generation, for when we use <debug-symbols>on/<debug-store>database
351 #
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
353 #
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
356 #
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.
359 #
360
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(
363     'msvc.compile.c',
364     compile_action,
365     function=compile_c,
366     bound_list=['PDB_NAME'])
367
368 engine.register_action(
369     'msvc.compile.c++',
370     compile_action,
371     function=compile_cpp,
372     bound_list=['PDB_NAME'])
373
374
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)"'
376
377 engine.register_action(
378     'msvc.preprocess.c',
379     preprocess_action,
380     function=compile_c_preprocess,
381     bound_list=['PDB_NAME'])
382
383 engine.register_action(
384     'msvc.preprocess.c++',
385     preprocess_action,
386     function=compile_cpp_preprocess,
387     bound_list=['PDB_NAME'])
388
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')
395
396 def preprocess_c_cpp(targets,sources=None):
397     #same as above
398     return compile_c_cpp(targets,sources)
399
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.
403
404 engine.register_action(
405     'msvc.compile.c.pch',
406     None, # action set by the function
407     function=compile_c_pch)
408
409 engine.register_action(
410     'msvc.compile.c++.pch',
411     None, # action set by the function
412     function=compile_cpp_pch)
413
414
415 # See midl.py for details.
416 #
417 engine.register_action(
418     'msvc.compile.idl',
419     '''$(.IDL) /nologo @"@($(<[1]:W).rsp:E=
420 "$(>:W)" 
421 -D$(DEFINES)
422 "-I$(INCLUDES:W)"
423 -U$(UNDEFS)
424 $(MIDLFLAGS)
425 /tlb "$(<[1]:W)"
426 /h "$(<[2]:W)"
427 /iid "$(<[3]:W)"
428 /proxy "$(<[4]:W)"
429 /dlldata "$(<[5]:W)")"
430     {touch} "$(<[4]:W)"
431     {touch} "$(<[5]:W)"'''.format(touch=common.file_creation_command()))
432
433 engine.register_action(
434     'msvc.compile.mc',
435     '$(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"')
436
437 engine.register_action(
438     'msvc.compile.rc',
439     '$(.RC) -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)"')
440
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)
444
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)
448
449
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
454 # want it.
455
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).
459
460 if not on_cygwin():
461     engine.register_action(
462         'msvc.link',
463         '''$(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
464 "$(>)"
465 $(LIBRARIES_MENTIONED_BY_FILE)
466 $(LIBRARIES)
467 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
468 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
469 if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%''',
470         function=manifest,
471         bound_list=['PDB_NAME','DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
472
473     engine.register_action(
474         'msvc.manifest',
475         '''if exist "$(<[1]).manifest" (
476             $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
477         )''')
478
479     engine.register_action(
480         'msvc.link.dll',
481         '''$(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
482 "$(>)"
483 $(LIBRARIES_MENTIONED_BY_FILE)
484 $(LIBRARIES)
485 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
486 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
487 if %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL%''',
488         function=link_dll,
489         bound_list=['DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
490     
491     engine.register_action(
492         'msvc.manifest.dll',
493         '''if exist "$(<[1]).manifest" (
494             $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
495         )''')
496 else:
497     engine.register_action(
498         'msvc.link',
499         '''$(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
500 "$(>)"
501 $(LIBRARIES_MENTIONED_BY_FILE)
502 $(LIBRARIES)
503 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
504 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
505         function=manifest,
506         bound_list=['PDB_NAME','DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
507
508     engine.register_action(
509         'msvc.manifest',
510         '''if test -e "$(<[1]).manifest"; then
511             $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
512         fi''')
513
514     engine.register_action(
515         'msvc.link.dll',
516         '''$(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(<[2]:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=
517 "$(>)"
518 $(LIBRARIES_MENTIONED_BY_FILE)
519 $(LIBRARIES)
520 "$(LIBRARY_OPTION)$(FINDLIBS_ST).lib"
521 "$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"''',
522         function=link_dll,
523         bound_list=['DEF_FILE','LIBRARIES_MENTIONED_BY_FILE'])
524     
525     engine.register_action(
526         'msvc.manifest.dll',
527         '''if test -e "$(<[1]).manifest"; then
528             $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
529         fi''')
530
531
532 ################################################################################
533 #
534 # Classes.
535 #
536 ################################################################################
537
538 class MsvcPchGenerator(pch.PchGenerator):
539
540     # Inherit the __init__ method
541
542     def run_pch(self, project, name, prop_set, sources):
543         # Find the header in sources. Ignore any CPP sources.
544         pch_header = None
545         pch_source = None
546         for s in sources:
547             if type.is_derived(s.type(), 'H'):
548                 pch_header = s
549             elif type.is_derived(s.type(), 'CPP') or type.is_derived(s.type(), 'C'):
550                 pch_source = s
551             
552         if not pch-header:
553             raise RuntimeError( "can not build pch without pch-header" )
554
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)
559         pch_file = None
560         for g in generated:
561             if type.is_derived(g.type(), 'PCH'):
562                 pch_file = g
563         return property_set.create([Property('pch-header',pch_header),Property('pch-file',pch_file)]+generated)
564
565
566 ################################################################################
567 #
568 # Local rules.
569 #
570 ################################################################################
571
572 # Detects versions listed as '_known_versions' by checking registry information,
573 # environment variables & default paths. Supports both native Windows and
574 # Cygwin.
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():
580                 vc_path = None
581                 for x in [ '', 'Wow6432Node\\' ]:
582                     try:
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]
585                     except:
586                         pass
587                 if vc_path:
588                     vc_path = os.path.join(vc_path,'bin')
589                     register_configuration(version,os.path.normpath(vc_path))
590
591     for i in _known_versions:
592         if not i in __versions.all():
593             register_configuration(i,default_path(i))
594
595
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
599 # registered yet).
600 #
601
602 def configure_really(version=None, options=[]):
603     v = version
604     if not v:
605         # Take the first registered (i.e. auto-detected) version.
606         version = __versions.first()
607         v = version
608         
609         # Note: 'version' can still be empty at this point if no versions have
610         # been auto-detected.
611         if not version:
612             version = "default"
613
614     # Version alias -> real version number.
615     version = globals().get("__version_alias_{}".format(version), version)
616
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))
623     else:
624         # Register a new configuration.
625         __versions.register(version)
626
627         # Add user-supplied to auto-detected options.
628         version_opts = __versions.get(version, 'options')
629         if (version_opts):
630             options = version_opts + options
631
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)
638         
639         # If version is specified, we try to search first in default paths, and
640         # only then in PATH.
641         command = common.get_invocation_command('msvc', 'cl.exe', command, default_paths(version))
642         common.handle_options('msvc', conditions, command, options)
643         
644         if not version:
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):
650                 version = '11.0'
651             if re.search("Microsoft Visual Studio 10", command):
652                 version = '10.0'
653             elif re.search("Microsoft Visual Studio 9", command):
654                 version = '9.0'
655             elif re.search("Microsoft Visual Studio 8", command):
656                 version = '8.0'
657             elif re.search("NET 2003[\/\\]VC7", command):
658                 version = '7.1'
659             elif re.search("Microsoft Visual C\\+\\+ Toolkit 2003", command):
660                 version = '7.1toolkit'
661             elif re.search(".NET[\/\\]VC7", command):
662                 version = '7.0'
663             else:
664                 version = '6.0'
665
666         # Generate and register setup command.
667
668         below_8_0 = re.search("^[67]\\.",version) != None
669
670         if below_8_0:
671             cpu = ['i386']
672         else:
673             cpu = ['i386', 'amd64', 'ia64']
674
675         setup_scripts = {}
676
677         if command:
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
685             # toolset version.
686             command = common.get_absolute_tool_path(command)
687         
688         if 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.
695
696             # Default setup scripts provided with different VC distributions:
697             #
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.
701             #
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.
711
712             global_setup = feature.get_values('<setup>',options)
713             if global_setup:
714                 global_setup = global_setup[0]
715             else:
716                 global_setup = None
717
718             if not below_8_0 and not global_setup:
719                 global_setup = locate_default_setup(command,parent,'vcvarsall.bat')
720
721
722             default_setup = {
723                 'amd64' : 'vcvarsx86_amd64.bat',
724                 'i386' : 'vcvars32.bat',
725                 'ia64' : 'vcvarsx86_ia64.bat' }
726
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',
733                 'i386' : 'x86',
734                 'ia64' : 'x86_ia64' }
735
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)
743             # Windows.
744             #
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'
753
754             setup_prefix = "call "
755             setup_suffix = """ >nul\n"""
756             if on_cygwin():
757                 setup_prefix = "cmd.exe /S /C call "
758                 setup_suffix = " \">nul\" \"&&\" "
759
760             for c in cpu:
761                 setup_options = None
762                 setup_cpu = feature.get_values('<setup-{}>'.format(c),options)
763
764                 if not setup_cpu:
765                     if global_setup:
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 ]
773                     else:
774                         setup_cpu = locate_default_setup(command, parent, default_setup[ c ])
775
776                 # Cygwin to Windows path translation.
777                 # setup-$(c) = "\""$(setup-$(c):W)"\"" ;
778
779                 # Append setup options to the setup name and add the final setup
780                 # prefix & suffix.
781                 setup_scripts[ c ] = '{}"{}" {}{}'.format(setup_prefix, setup_cpu, setup_options, setup_suffix)
782
783         # Get tool names (if any) and finish setup.
784         compiler = feature.get_values("<compiler>", options)
785         if not compiler:
786             compiler = "cl"
787
788         linker = feature.get_values("<linker>", options)
789         if not linker:
790             linker = "link"
791
792         resource_compiler = feature.get_values("<resource-compiler>", options)
793         if not resource_compiler:
794             resource_compiler = "rc"
795
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'
801
802         assembler = feature.get_values('<assembler>',options)
803         
804         idl_compiler = feature.get_values('<idl-compiler>',options)
805         if not idl_compiler:
806             idl_compiler = 'midl'
807
808         mc_compiler = feature.get_values('<mc-compiler>',options)
809         if not mc_compiler:
810             mc_compiler = 'mc'
811
812         manifest_tool = feature.get_values('<manifest-tool>',options)
813         if not manifest_tool:
814             manifest_tool = 'mt'
815
816         cc_filter = feature.get_values('<compiler-filter>',options)
817
818         for c in cpu:
819             cpu_conditions = [ condition + '/' + arch for arch in globals()['__cpu_arch_{}'.format(c)] for condition in conditions ]
820             
821             setup_script = setup_scripts.get(c, '')
822
823             if debug():
824                 for cpu_condition in cpu_conditions:
825                     print "notice: [msvc-cfg] condition: '{}', setup: '{}'".format(cpu_condition,setup_script)
826
827             cpu_assembler = assembler
828             if not cpu_assembler:
829                 cpu_assembler = locals()['default_assembler_{}'.format(c)]
830
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)])
839
840             if cc_filter:
841                 toolset.flags('msvc', '.CC.FILTER', cpu_conditions, ['"|" {}'.format(cc_filter)])
842
843         # Set version-specific flags.
844         configure_version_specific('msvc', version, conditions)
845
846
847 # Returns the default installation path for the given version.
848 #
849 def default_path(version):
850     # Use auto-detected path if possible.
851     options = __versions.get(version, 'options')
852     tmp_path = None
853     if options:
854         tmp_path = feature.get_values('<command>', options)
855
856     if tmp_path:
857         tmp_path="".join(tmp_path)
858         tmp_path=os.path.dirname(tmp_path)
859     else:
860         env_var_var_name = '__version_{}_env'.format(version.replace('.','_'))
861         vc_path = None
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]
866         if vc_path:
867             vc_path = os.path.join(vc_path,globals()['__version_{}_envpath'.format(version.replace('.','_'))])
868             tmp_path = os.path.normpath(vc_path)
869
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]))
873     return tmp_path
874
875
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)
878 #
879 def default_paths(version = None):
880     possible_paths = []
881     if version:
882         path = default_path(version)
883         if path:
884             possible_paths.append(path)
885     else:
886         for i in _known_versions:
887             path = default_path(i)
888             if path:
889                 possible_paths.append(path)
890     return possible_paths
891
892
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
897     # whatever.gch.
898     def generated_targets(self, sources, prop_set, project, name):
899         result = builtin.LinkingGenerator.generated_targets(self, sources, prop_set, project, name)
900         if result:
901             name_main = result[0].name()
902             action = result[0].action()
903             
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)
924         return result
925
926
927 # Unsafe worker rule for the register-toolset() rule. Must not be called
928 # multiple times.
929
930 def register_toolset_really():
931     feature.extend('toolset', ['msvc'])
932
933     # Intel and msvc supposedly have link-compatible objects.
934     feature.subfeature( 'toolset', 'msvc', 'vendor', 'intel', ['propagated', 'optional'])
935
936     # Inherit MIDL flags.
937     toolset.inherit_flags('msvc', 'midl')
938
939     # Inherit MC flags.
940     toolset.inherit_flags('msvc','mc')
941
942     # Dynamic runtime comes only in MT flavour.
943     toolset.add_requirements(['<toolset>msvc,<runtime-link>shared:<threading>multi'])
944
945     # Declare msvc toolset specific features.
946     feature.feature('debug-store', ['object', 'database'], ['propagated'])
947     feature.feature('pch-source', [], ['dependency', 'free'])
948
949     # Declare generators.
950
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
953     # .rsp file.
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']))
956
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'])
962
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'])
967
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')
970
971     generators.register_standard('msvc.compile.mc', ['MC'], ['H','RC'], ['<toolset>msvc'])
972     generators.override('msvc.compile.mc', 'mc.compile')
973
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']))
979
980     generators.override('msvc.compile.c.pch', 'pch.default-c-pch-generator')
981     generators.override('msvc.compile.c++.pch', 'pch.default-cpp-pch-generator')
982
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>'])
986
987     #
988     # Declare flags for compilation.
989     #
990     toolset.flags('msvc.compile', 'CFLAGS', ['<optimization>speed'], ['/O2'])
991     toolset.flags('msvc.compile', 'CFLAGS', ['<optimization>space'], ['/O1'])
992
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'])
995
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'])
1002
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'])
1007
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'])
1012
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'])
1020
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'])
1023
1024     toolset.flags('msvc.compile', 'OPTIONS', [], ['<cflags>'])
1025     toolset.flags('msvc.compile.c++', 'OPTIONS', [], ['<cxxflags>'])
1026
1027     toolset.flags('msvc.compile', 'PDB_CFLAG', ['<debug-symbols>on/<debug-store>database'],['/Fd'])
1028
1029     toolset.flags('msvc.compile', 'DEFINES', [], ['<define>'])
1030     toolset.flags('msvc.compile', 'UNDEFS', [], ['<undef>'])
1031     toolset.flags('msvc.compile', 'INCLUDES', [], ['<include>'])
1032
1033     # Declare flags for the assembler.
1034     toolset.flags('msvc.compile.asm', 'USER_ASMFLAGS', [], ['<asmflags>'])
1035
1036     toolset.flags('msvc.compile.asm', 'ASMFLAGS', ['<debug-symbols>on'], ['/Zi', '/Zd'])
1037
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'])
1042
1043     toolset.flags('msvc.compile.asm', 'DEFINES', [], ['<define>'])
1044
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>'])
1049
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'])
1053
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'])
1059
1060     toolset.flags('msvc.link', 'OPTIONS', [], ['<linkflags>'])
1061     toolset.flags('msvc.link', 'LINKPATH', [], ['<library-path>'])
1062
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>'])
1067
1068     toolset.flags('msvc.archive', 'AROPTIONS', [], ['<archiveflags>'])
1069
1070
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.
1074 #
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
1079 # longer important.
1080 #
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):
1084             return setup
1085     return None
1086
1087
1088 # Validates given path, registers found configuration and prints debug
1089 # information about it.
1090 #
1091 def register_configuration(version, path=None):
1092     if path:
1093         command = os.path.join(path, 'cl.exe')
1094         if os.path.exists(command):
1095             if debug():
1096                 print "notice: [msvc-cfg] msvc-$(version) detected, command: ''".format(version,command)
1097             __versions.register(version)
1098             __versions.set(version,'options',['<command>{}'.format(command)])
1099
1100
1101 ################################################################################
1102 #
1103 #   Startup code executed when loading this module.
1104 #
1105 ################################################################################
1106
1107 # Similar to Configurations, but remembers the first registered configuration.
1108 class MSVCConfigurations(Configurations):
1109     def __init__(self):
1110         Configurations.__init__(self)
1111         self.first_ = None
1112
1113     def register(self, id):
1114         Configurations.register(self,id)
1115         if not self.first_:
1116             self.first_ = id
1117
1118     def first(self):
1119         return self.first_
1120     
1121
1122 # List of all registered configurations.
1123 __versions = MSVCConfigurations()
1124
1125 # Supported CPU architectures.
1126 __cpu_arch_i386 = [
1127     '<architecture>/<address-model>', 
1128     '<architecture>/<address-model>32',
1129     '<architecture>x86/<address-model>',
1130     '<architecture>x86/<address-model>32']
1131
1132 __cpu_arch_amd64 = [
1133     '<architecture>/<address-model>64',
1134     '<architecture>x86/<address-model>64']
1135
1136 __cpu_arch_ia64 = [
1137     '<architecture>ia64/<address-model>',
1138     '<architecture>ia64/<address-model>64']
1139
1140
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']
1156
1157
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']
1160
1161 # Version aliases.
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'
1169
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"
1182
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'
1188
1189 # Path to the folder containing "cl.exe" relative to the value of the
1190 # corresponding environment variable.
1191 __version_7_1toolkit_envpath = 'bin' ;
1192 #
1193 #
1194 # Auto-detect all the available msvc installations on the system.
1195 auto_detect_toolset_versions()
1196
1197 # And finally trigger the actual Boost Build toolset registration.
1198 register_toolset()