• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2017 Rene Rivera
7# Copyright (c) 2008 Jurko Gospodnetic
8# Copyright (c) 2014 Microsoft Corporation
9# Copyright (c) 2019 Michał Janiszewski
10# Copyright (c) 2020 Nikita Kniazev
11#
12# Distributed under the Boost Software License, Version 1.0.
13# (See accompanying file LICENSE_1_0.txt or copy at
14# http://www.boost.org/LICENSE_1_0.txt)
15
16#| tag::doc[]
17
18[[bbv2.reference.tools.compiler.msvc]]
19= Microsoft Visual C++
20
21The `msvc` module supports the
22http://msdn.microsoft.com/visualc/[Microsoft Visual C++] command-line
23tools on Microsoft Windows. The supported products and versions of
24command line tools are listed below:
25
26* Visual Studio 2019-14.2
27* Visual Studio 2017—14.1
28* Visual Studio 2015—14.0
29* Visual Studio 2013—12.0
30* Visual Studio 2012—11.0
31* Visual Studio 2010—10.0
32* Visual Studio 2008—9.0
33* Visual Studio 2005—8.0
34* Visual Studio .NET 2003—7.1
35* Visual Studio .NET—7.0
36* Visual Studio 6.0, Service Pack 5--6.5
37
38The user would then call the boost build executable with the toolset set
39equal to `msvc-[version number]` for example to build with Visual Studio
402019 one could run:
41
42----
43.\b2 toolset=msvc-14.2 target
44----
45
46The `msvc` module is initialized using the following syntax:
47
48----
49using msvc : [version] : [c++-compile-command] : [compiler options] ;
50----
51
52This statement may be repeated several times, if you want to configure
53several versions of the compiler.
54
55If the version is not explicitly specified, the most recent version
56found in the registry will be used instead. If the special value `all`
57is passed as the version, all versions found in the registry will be
58configured. If a version is specified, but the command is not, the
59compiler binary will be searched in standard installation paths for that
60version, followed by PATH.
61
62The compiler command should be specified using forward slashes, and
63quoted.
64
65The following options can be provided, using
66_`<option-name>option-value syntax`_:
67
68`cflags`::
69Specifies additional compiler flags that will be used when compiling C
70sources.
71
72`cxxflags`::
73Specifies additional compiler flags that will be used when compiling C++
74sources.
75
76`compileflags`::
77Specifies additional compiler flags that will be used when compiling both C
78and C++ sources.
79
80`linkflags`::
81Specifies additional command line options that will be passed to the linker.
82
83`assembler`::
84The command that compiles assembler sources. If not specified, `ml`
85will be used. The command will be invoked after the setup script was
86executed and adjusted the PATH variable.
87
88`compiler`::
89The command that compiles C and C++ sources. If not specified, `cl`
90will be used. The command will be invoked after the setup script was
91executed and adjusted the PATH variable.
92
93`compiler-filter`::
94Command through which to pipe the output of running the compiler. For
95 example to pass the output to STLfilt.
96
97`idl-compiler`::
98The command that compiles Microsoft COM interface definition files. If
99not specified, `midl` will be used. The command will be invoked after
100the setup script was executed and adjusted the PATH variable.
101
102`linker`::
103The command that links executables and dynamic libraries. If not
104specified, `link` will be used. The command will be invoked after the
105setup script was executed and adjusted the PATH variable.
106
107`mc-compiler`::
108The command that compiles Microsoft message catalog files. If not
109specified, `mc` will be used. The command will be invoked after the
110setup script was executed and adjusted the PATH variable.
111
112`resource-compiler`::
113The command that compiles resource files. If not specified, `rc` will
114be used. The command will be invoked after the setup script was
115executed and adjusted the PATH variable.
116
117`setup`::
118The filename of the global environment setup script to run before
119invoking any of the tools defined in this toolset. Will not be used in
120case a target platform specific script has been explicitly specified
121for the current target platform. Used setup script will be passed the
122target platform identifier (x86, x86_amd64, x86_ia64, amd64 or ia64)
123as a parameter. If not specified a default script is chosen based on
124the used compiler binary, e.g. `vcvars32.bat` or `vsvars32.bat`.
125
126`setup-amd64`; `setup-i386`; `setup-ia64`::
127The filename of the target platform specific environment setup script
128to run before invoking any of the tools defined in this toolset. If
129not specified the global environment setup script is used.
130
131[[bbv2.reference.tools.compiler.msvc.64]]
132== 64-bit support
133
134Starting with version 8.0, Microsoft Visual Studio can generate binaries
135for 64-bit processor, both 64-bit flavours of x86 (codenamed
136AMD64/EM64T), and Itanium (codenamed IA64). In addition, compilers that
137are itself run in 64-bit mode, for better performance, are provided. The
138complete list of compiler configurations are as follows (we abbreviate
139AMD64/EM64T to just AMD64):
140
141* 32-bit x86 host, 32-bit x86 target
142* 32-bit x86 host, 64-bit AMD64 target
143* 32-bit x86 host, 64-bit IA64 target
144* 64-bit AMD64 host, 64-bit AMD64 target
145* 64-bit IA64 host, 64-bit IA64 target
146
147The 32-bit host compilers can be always used, even on 64-bit Windows. On
148the contrary, 64-bit host compilers require both 64-bit host processor
149and 64-bit Windows, but can be faster. By default, only 32-bit host,
15032-bit target compiler is installed, and additional compilers need to be
151installed explicitly.
152
153To use 64-bit compilation you should:
154
1551. Configure you compiler as usual. If you provide a path to the
156compiler explicitly, provide the path to the 32-bit compiler. If you try
157to specify the path to any of 64-bit compilers, configuration will not
158work.
1592. When compiling, use `address-model=64`, to generate AMD64 code.
1603. To generate IA64 code, use `architecture=ia64`
161
162The (AMD64 host, AMD64 target) compiler will be used automatically when
163you are generating AMD64 code and are running 64-bit Windows on AMD64.
164The (IA64 host, IA64 target) compiler will never be used, since nobody
165has an IA64 machine to test.
166
167It is believed that AMD64 and EM64T targets are essentially compatible.
168The compiler options `/favor:AMD64` and `/favor:EM64T`, which are
169accepted only by AMD64 targeting compilers, cause the generated code to
170be tuned to a specific flavor of 64-bit x86. B2 will make use
171of those options depending on the value of the`instruction-set` feature.
172
173[[bbv2.reference.tools.compiler.msvc.winrt]]
174== Windows Runtime support
175
176Starting with version 11.0, Microsoft Visual Studio can produce binaries
177for Windows Store and Phone in addition to traditional Win32 desktop. To
178specify which Windows API set to target, use the `windows-api` feature.
179Available options are `desktop`, `store`, or `phone`. If not specified,
180`desktop` will be used.
181
182When using `store` or `phone` the specified toolset determines what
183Windows version is targeted. The following options are available:
184
185* Windows 8.0: toolset=msvc-11.0 windows-api=store
186* Windows 8.1: toolset=msvc-12.0 windows-api=store
187* Windows Phone 8.0: toolset=msvc-11.0 windows-api=phone
188* Windows Phone 8.1: toolset=msvc-12.0 windows-api=phone
189
190For example use the following to build for Windows Store 8.1 with the
191ARM architecture:
192
193----
194.\b2 toolset=msvc-12.0 windows-api=store architecture=arm
195----
196
197Note that when targeting Windows Phone 8.1, version 12.0 didn't include
198the vcvars phone setup scripts. They can be separately downloaded from
199http://blogs.msdn.com/b/vcblog/archive/2014/07/18/using-boost-libraries-in-windows-store-and-phone-applications.aspx[here].
200
201|# # end::doc[]
202
203
204################################################################################
205#
206# MSVC Boost Build toolset module.
207# --------------------------------
208#
209# All toolset versions need to have their location either auto-detected or
210# explicitly specified except for the special 'default' version that expects the
211# environment to find the needed tools or report an error.
212#
213################################################################################
214
215import "class" : new ;
216import common ;
217import feature ;
218import generators ;
219import mc ;
220import midl ;
221import os ;
222import path ;
223import pch ;
224import project ;
225import property ;
226import property-set ;
227import rc ;
228import sequence ;
229import set ;
230import toolset ;
231import type ;
232import virtual-target ;
233import version ;
234
235
236type.register MANIFEST : manifest ;
237
238#| tag::embed-doc[]
239
240[[bbv2.builtin.features.embed-manifest]]`embed-manifest`::
241*Allowed values:* `on`, `off`.
242+
243This feature is specific to the `msvc` toolset (see <<Microsoft Visual C++>>),
244and controls whether the manifest files should be embedded inside executables
245and shared libraries, or placed alongside them. This feature corresponds to the
246IDE option found in the project settings dialog, under Configuration Properties
247-> Manifest Tool -> Input and Output -> Embed manifest.
248
249|# # end::embed-doc[]
250
251feature.feature embed-manifest : on off : incidental propagated ;
252
253#| tag::embed-doc[]
254
255[[bbv2.builtin.features.embed-manifest-file]]`embed-manifest-file`::
256This feature is specific to the `msvc` toolset (see <<Microsoft Visual C++>>),
257and controls which manifest files should be embedded inside executables and
258shared libraries. This feature corresponds to the IDE option found in the
259project settings dialog, under Configuration Properties -> Manifest Tool ->
260Input and Output -> Additional Manifest Files.
261
262|# # end::embed-doc[]
263
264feature.feature embed-manifest-file : : free dependency ;
265
266#| tag::embed-doc[]
267
268[[bbv2.builtin.features.embed-manifest-via]]`embed-manifest-via`::
269This feature is specific to the `msvc` toolset (see <<Microsoft Visual C++>>),
270and controls whether a manifest should be embedded via linker or manifest tool.
271
272|# # end::embed-doc[]
273
274feature.feature embed-manifest-via : mt linker : incidental propagated ;
275
276type.register PDB : pdb ;
277
278
279################################################################################
280#
281# Public rules.
282#
283################################################################################
284
285# Initialize a specific toolset version configuration. As the result, path to
286# compiler and, possible, program names are set up, and will be used when that
287# version of compiler is requested. For example, you might have:
288#
289#    using msvc : 6.5 : cl.exe ;
290#    using msvc : 7.0 : Y:/foo/bar/cl.exe ;
291#
292# The version parameter may be omitted:
293#
294#    using msvc : : Z:/foo/bar/cl.exe ;
295#
296# The following keywords have special meanings when specified as versions:
297#   - all     - all detected but not yet used versions will be marked as used
298#               with their default options.
299#   - default - this is an equivalent to an empty version.
300#
301# Depending on a supplied version, detected configurations and presence 'cl.exe'
302# in the path different results may be achieved. The following table describes
303# the possible scenarios:
304#
305#                                      Nothing            "x.y"
306# Passed   Nothing       "x.y"         detected,          detected,
307# version  detected      detected      cl.exe in path     cl.exe in path
308#
309# default  Error         Use "x.y"     Create "default"   Use "x.y"
310# all      None          Use all       None               Use all
311# x.y      -             Use "x.y"     -                  Use "x.y"
312# a.b      Error         Error         Create "a.b"       Create "a.b"
313#
314# "x.y" - refers to a detected version;
315# "a.b" - refers to an undetected version.
316#
317# FIXME: Currently the command parameter and the <compiler> property parameter
318# seem to overlap in duties. Remove this duplication. This seems to be related
319# to why someone started preparing to replace init with configure rules.
320#
321rule init (
322    # The msvc version being configured. When omitted the tools invoked when no
323    # explicit version is given will be configured.
324    version ?
325
326    # The command used to invoke the compiler. If not specified:
327    #   - if version is given, default location for that version will be
328    #     searched
329    #
330    #   - if version is not given, default locations for MSVC 9.0, 8.0, 7.1, 7.0
331    #     and 6.* will be searched
332    #
333    #   - if compiler is not found in the default locations, PATH will be
334    #     searched.
335    : command *
336
337    # Options may include:
338    #
339    #     All options shared by multiple toolset types as handled by the
340    #   common.handle-options() rule, e.g. <cflags>, <compileflags>, <cxxflags>,
341    #   <fflags> & <linkflags>.
342    #
343    #   <assembler>
344    #   <compiler>
345    #   <idl-compiler>
346    #   <linker>
347    #   <mc-compiler>
348    #   <resource-compiler>
349    #       Exact tool names to be used by this msvc toolset configuration.
350    #
351    #   <compiler-filter>
352    #       Command through which to pipe the output of running the compiler.
353    #     For example to pass the output to STLfilt.
354    #
355    #   <setup>
356    #       Global setup command to invoke before running any of the msvc tools.
357    #     It will be passed additional option parameters depending on the actual
358    #     target platform.
359    #
360    #   <setup-amd64>
361    #   <setup-i386>
362    #   <setup-ia64>
363    #   <setup-arm>
364    #   <setup-phone-i386>
365    #   <setup-phone-arm>
366    #       Platform specific setup command to invoke before running any of the
367    #     msvc tools used when builing a target for a specific platform, e.g.
368    #     when building a 32 or 64 bit executable.
369    #
370    #   <rewrite-setup-scripts>
371    #       Whether to rewrite setup scripts. New scripts will be output in
372    #     build tree and will be used instead of originals in build actions.
373    #     Possible values:
374    #       * on - rewrite scripts, if they do not already exist (default)
375    #       * always - always rewrite scripts, even if they already exist
376    #       * off - use original setup scripts
377    : options *
378)
379{
380    if $(command)
381    {
382        options += <command>$(command) ;
383    }
384    configure $(version) : $(options) ;
385}
386
387
388# 'configure' is a newer version of 'init'. The parameter 'command' is passed as
389# a part of the 'options' list. See the 'init' rule comment for more detailed
390# information.
391#
392rule configure ( version ? : options * )
393{
394    switch $(version)
395    {
396        case "all" :
397            if $(options)
398            {
399                import errors ;
400                errors.error "MSVC toolset configuration: options should be"
401                    "empty when '$(version)' is specified." ;
402            }
403
404            # Configure (i.e. mark as used) all registered versions.
405            local all-versions = [ $(.versions).all ] ;
406            if ! $(all-versions)
407            {
408                if $(.debug-configuration)
409                {
410                    ECHO "notice: [msvc-cfg] Asked to configure all registered"
411                        "msvc toolset versions when there are none currently"
412                        "registered." ;
413                }
414            }
415            else
416            {
417                for local v in $(all-versions)
418                {
419                    # Note that there is no need to skip already configured
420                    # versions here as this will request configure-really rule
421                    # to configure the version using default options which will
422                    # in turn cause it to simply do nothing in case the version
423                    # has already been configured.
424                    configure-really $(v) ;
425                }
426            }
427
428        case "default" :
429            configure-really : $(options) ;
430
431        case * :
432            configure-really $(version) : $(options) ;
433    }
434}
435
436
437# Sets up flag definitions dependent on the compiler version used.
438# - 'version' is the version of compiler in N.M format.
439# - 'conditions' is the property set to be used as flag conditions.
440# - 'toolset' is the toolset for which flag settings are to be defined.
441#   This makes the rule reusable for other msvc-option-compatible compilers.
442#
443rule configure-version-specific ( toolset : version : conditions )
444{
445    toolset.push-checking-for-flags-module unchecked ;
446    # Starting with versions 7.0, the msvc compiler have the /Zc:forScope and
447    # /Zc:wchar_t options that improve C++ standard conformance, but those
448    # options are off by default. If we are sure that the msvc version is at
449    # 7.*, add those options explicitly. We can be sure either if user specified
450    # version 7.* explicitly or if we auto-detected the version ourselves.
451    if ! [ MATCH ^(6\\.) : $(version) ]
452    {
453        toolset.flags $(toolset).compile CFLAGS $(conditions) : "/Zc:forScope" "/Zc:wchar_t" ;
454        toolset.flags $(toolset).compile.c++ C++FLAGS $(conditions) : /wd4675 ;
455
456        # Explicitly disable the 'function is deprecated' warning. Some msvc
457        # versions have a bug, causing them to emit the deprecation warning even
458        # with /W0.
459        toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>off : /wd4996 ;
460
461        if [ MATCH "^([78]\\.)" : $(version) ]
462        {
463            # 64-bit compatibility warning deprecated since 9.0, see
464            # http://msdn.microsoft.com/en-us/library/yt4xw8fh.aspx
465            toolset.flags $(toolset).compile CFLAGS $(conditions)/<warnings>all : /Wp64 ;
466        }
467    }
468
469    # 12.0 (VS2013 Update 2) introduced /Zc:inline opt-in standard conformance
470    # compiler flag that also similar to linker /opt:ref removes unreferenced
471    # variables and functions that have internal linkage
472    if ! [ version.version-less [ SPLIT_BY_CHARACTERS [ MATCH "^([0123456789.]+)" : $(version) ] : . ] : 12 ]
473    {
474        toolset.flags $(toolset).compile CFLAGS $(conditions) : "/Zc:inline" ;
475
476        # /Gy analog for variables: https://devblogs.microsoft.com/cppblog/introducing-gw-compiler-switch/
477        toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed $(conditions)/<optimization>space : /Gw ;
478    }
479
480    # 14.0 introduced /Zc:throwingNew opt-in flag that disables a workaround
481    # for not throwing operator new in VC up to 6.0
482    if ! [ version.version-less [ SPLIT_BY_CHARACTERS [ MATCH "^([0123456789.]+)" : $(version) ] : . ] : 14 ]
483    {
484        toolset.flags $(toolset).compile CFLAGS $(conditions) : "/Zc:throwingNew" ;
485    }
486
487    #
488    # Processor-specific optimization.
489    #
490
491    if [ MATCH "^([67])" : $(version) ]
492    {
493        # 8.0 deprecates some of the options.
494        toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed $(conditions)/<optimization>space : /Ogiy /Gs ;
495        toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>speed : /Ot ;
496        toolset.flags $(toolset).compile CFLAGS $(conditions)/<optimization>space : /Os ;
497
498        toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set> : /GB ;
499        toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>i486 : /G4 ;
500        toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g5) : /G5 ;
501        toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g6) : /G6 ;
502        toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-i386)/<instruction-set>$(.cpu-type-g7) : /G7 ;
503
504        # Improve floating-point accuracy. Otherwise, some of C++ Boost's "math"
505        # tests will fail.
506        toolset.flags $(toolset).compile CFLAGS $(conditions) : /Op ;
507
508        # 7.1 and below have single-threaded static RTL.
509        toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>off/<runtime-link>static/<threading>single : /ML ;
510        toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>on/<runtime-link>static/<threading>single : /MLd ;
511    }
512    else
513    {
514        # 8.0 and above adds some more options.
515        toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set> : "/favor:blend" ;
516        toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set>$(.cpu-type-em64t) : "/favor:EM64T" ;
517        toolset.flags $(toolset).compile CFLAGS $(conditions)/$(.cpu-arch-amd64)/<instruction-set>$(.cpu-type-amd64) : "/favor:AMD64" ;
518
519        # 8.0 and above only has multi-threaded static RTL.
520        toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>off/<runtime-link>static/<threading>single : /MT ;
521        toolset.flags $(toolset).compile CFLAGS $(conditions)/<runtime-debugging>on/<runtime-link>static/<threading>single : /MTd ;
522
523        # Specify target machine type so the linker will not need to guess.
524        toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-amd64) : "/MACHINE:X64" ;
525        toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-i386)  : "/MACHINE:X86" ;
526        toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-ia64)  : "/MACHINE:IA64" ;
527        toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-arm)   : "/MACHINE:ARM" ;
528        toolset.flags $(toolset).link LINKFLAGS $(conditions)/$(.cpu-arch-arm64) : "/MACHINE:ARM64" ;
529
530        if [ version.version-less [ SPLIT_BY_CHARACTERS [ MATCH "^([0123456789.]+)" : $(version) ] : . ] : 11 ]
531        {
532            # Make sure that manifest will be generated even if there is no
533            # dependencies to put there.
534            toolset.flags $(toolset).link LINKFLAGS $(conditions) : /MANIFEST ;
535        }
536        else
537        {
538            toolset.flags $(toolset).link LINKFLAGS $(conditions)/<embed-manifest-via>mt : /MANIFEST ;
539            toolset.flags $(toolset).link LINKFLAGS $(conditions)/<embed-manifest-via>linker/<embed-manifest>off : /MANIFEST ;
540            toolset.flags $(toolset).link LINKFLAGS $(conditions)/<embed-manifest-via>linker/<embed-manifest>on : "/MANIFEST:EMBED" ;
541
542            local conditionx = [ feature.split $(conditions) ] ;
543            toolset.add-defaults $(conditionx:J=,)\:<embed-manifest-via>linker ;
544        }
545    }
546
547    toolset.pop-checking-for-flags-module ;
548}
549
550# Feature for handling targeting different Windows API sets.
551feature.feature windows-api : desktop store phone : propagated composite link-incompatible ;
552feature.compose <windows-api>store : <define>WINAPI_FAMILY=WINAPI_FAMILY_APP <define>_WIN32_WINNT=0x0602
553    <linkflags>/APPCONTAINER ;
554feature.compose <windows-api>phone : <define>WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP <define>_WIN32_WINNT=0x0602
555    <linkflags>/APPCONTAINER <linkflags>"/NODEFAULTLIB:ole32.lib" <linkflags>"/NODEFAULTLIB:kernel32.lib" <linkflags>WindowsPhoneCore.lib ;
556feature.set-default windows-api : desktop ;
557
558
559# Registers this toolset including all of its flags, features & generators. Does
560# nothing on repeated calls.
561#
562rule register-toolset ( )
563{
564    if ! msvc in [ feature.values toolset ]
565    {
566        register-toolset-really ;
567    }
568}
569
570rule resolve-possible-msvc-version-alias ( version )
571{
572    if $(.version-alias-$(version))
573    {
574        version = $(.version-alias-$(version)) ;
575    }
576    return $(version) ;
577}
578
579
580# Declare action for creating static libraries. If library exists, remove it
581# before adding files. See
582# http://article.gmane.org/gmane.comp.lib.boost.build/4241 for rationale.
583if [ os.name ] in NT
584{
585    # The 'DEL' command would issue a message to stdout if the file does not
586    # exist, so need a check.
587    actions archive
588    {
589        if exist "$(<[1])" DEL "$(<[1])"
590        $(.SETUP) $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
591    }
592}
593else
594{
595    actions archive
596    {
597        $(.RM) "$(<[1])"
598        $(.SETUP) $(.LD) $(AROPTIONS) /out:"$(<[1])" @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
599    }
600}
601
602rule compile.asm ( targets + : sources * : properties * )
603{
604    set-setup-command $(targets) : $(properties) ;
605}
606
607actions compile.asm
608{
609    $(.SETUP) $(.ASM) -D$(ASMDEFINES) $(ASMFLAGS) $(USER_ASMFLAGS) $(.ASM_OUTPUT) "$(<:W)" "$(>:W)"
610}
611
612
613rule compile.c ( targets + : sources * : properties * )
614{
615    set-setup-command $(targets) : $(properties) ;
616    C++FLAGS on $(targets[1]) = ;
617    get-rspline $(targets) : -TC ;
618    compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
619}
620
621
622rule compile.c.preprocess ( targets + : sources * : properties * )
623{
624    set-setup-command $(targets) : $(properties) ;
625    C++FLAGS on $(targets[1]) = ;
626    get-rspline $(targets) : -TC ;
627    preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
628}
629
630
631rule compile.c.pch ( targets + : sources * : properties * )
632{
633    set-setup-command $(targets) : $(properties) ;
634    C++FLAGS on $(targets[1]) = ;
635    get-rspline $(targets[1]) : -TC ;
636    get-rspline $(targets[2]) : -TC ;
637    local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
638    if $(pch-source)
639    {
640        DEPENDS $(<) : $(pch-source) ;
641        compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
642    }
643    else
644    {
645        compile-c-c++-pch $(targets) : $(sources) ;
646    }
647}
648
649toolset.flags msvc YLOPTION : "-Yl" ;
650
651# Action for running the C/C++ compiler without using precompiled headers.
652#
653# WARNING: Synchronize any changes this in action with intel-win
654#
655# Notes regarding PDB generation, for when we use
656# <debug-symbols>on/<debug-store>database:
657#
658# 1. PDB_CFLAG is only set for <debug-symbols>on/<debug-store>database, ensuring
659#    that the /Fd flag is dropped if PDB_CFLAG is empty.
660#
661# 2. When compiling executables's source files, PDB_NAME is set on a per-source
662#    file basis by rule compile-c-c++. The linker will pull these into the
663#    executable's PDB.
664#
665# 3. When compiling library's source files, PDB_NAME is updated to <libname>.pdb
666#    for each source file by rule archive, as in this case compiler must be used
667#    to create a single PDB for our library.
668#
669actions compile-c-c++ bind PDB_NAME
670{
671    $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" $(.CC.FILTER)
672}
673
674actions preprocess-c-c++ bind PDB_NAME
675{
676    $(.SETUP) $(.CC) @"@($(<[1]:W).rsp:E="$(>[1]:W)" -E $(PDB_CFLAG)"$(PDB_NAME)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))" >"$(<[1]:W)"
677}
678
679rule compile-c-c++ ( targets + : sources * )
680{
681    DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ;
682    DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
683    PDB_NAME on $(<) = $(<[1]:S=.pdb) ;
684    LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
685}
686
687rule preprocess-c-c++ ( targets + : sources * )
688{
689    DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_HEADER) ] ;
690    DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
691    PDB_NAME on $(<) = $(<:S=.pdb) ;
692    LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
693}
694
695# Action for running the C/C++ compiler using precompiled headers. In addition
696# to whatever else it needs to compile, this action also adds a temporary source
697# .cpp file used to compile the precompiled headers themselves.
698#
699# The global .escaped-double-quote variable is used to avoid messing up Emacs
700# syntax highlighting in the messy N-quoted code below.
701actions compile-c-c++-pch
702{
703    $(.SETUP) $(.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)
704}
705
706
707# Action for running the C/C++ compiler using precompiled headers. An already
708# built source file for compiling the precompiled headers is expected to be
709# given as one of the source parameters.
710actions compile-c-c++-pch-s
711{
712    $(.SETUP) $(.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)
713}
714
715
716rule compile.c++ ( targets + : sources * : properties * )
717{
718    set-setup-command $(targets) : $(properties) ;
719    get-rspline $(targets) : -TP ;
720    compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
721}
722
723rule compile.c++.preprocess ( targets + : sources * : properties * )
724{
725    set-setup-command $(targets) : $(properties) ;
726    get-rspline $(targets) : -TP ;
727    preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
728}
729
730
731rule compile.c++.pch ( targets + : sources * : properties * )
732{
733    set-setup-command $(targets) : $(properties) ;
734    get-rspline $(targets[1]) : -TP ;
735    get-rspline $(targets[2]) : -TP ;
736    local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
737    if $(pch-source)
738    {
739        DEPENDS $(<) : $(pch-source) ;
740        compile-c-c++-pch-s $(targets) : $(sources) $(pch-source) ;
741    }
742    else
743    {
744        compile-c-c++-pch $(targets) : $(sources) ;
745    }
746}
747
748rule compile.idl ( targets + : sources * : properties * )
749{
750    set-setup-command $(targets) : $(properties) ;
751}
752
753# See midl.jam for details.
754#
755actions compile.idl
756{
757    $(.SETUP) $(.IDL) /nologo @"@($(<[1]:W).rsp:E=$(.nl)"$(>:W)" $(.nl)-D$(DEFINES) $(.nl)"-I$(INCLUDES:W)" $(.nl)-U$(UNDEFS) $(.nl)$(MIDLFLAGS) $(.nl)/tlb "$(<[1]:W)" $(.nl)/h "$(<[2]:W)" $(.nl)/iid "$(<[3]:W)" $(.nl)/proxy "$(<[4]:W)" $(.nl)/dlldata "$(<[5]:W)")"
758    $(.TOUCH_FILE) "$(<[4]:W)"
759    $(.TOUCH_FILE) "$(<[5]:W)"
760}
761
762rule compile.mc ( targets + : sources * : properties * )
763{
764    set-setup-command $(targets) : $(properties) ;
765}
766
767actions compile.mc
768{
769    $(.SETUP) $(.MC) $(MCFLAGS) -h "$(<[1]:DW)" -r "$(<[2]:DW)" "$(>:W)"
770}
771
772
773rule compile.rc ( targets + : sources * : properties * )
774{
775    set-setup-command $(targets) : $(properties) ;
776}
777
778actions compile.rc
779{
780    $(.SETUP) $(.RC) /nologo -l 0x409 -U$(UNDEFS) -D$(DEFINES) -I"$(INCLUDES:W)" -fo "$(<:W)" "$(>:W)"
781}
782
783toolset.uses-features msvc.link : <embed-manifest> <embed-manifest-file> ;
784
785rule link ( targets + : sources * : properties * )
786{
787    set-setup-command $(targets) : $(properties) ;
788    if <embed-manifest>on in $(properties) && <embed-manifest-via>mt in $(properties)
789    {
790        if [ feature.get-values <embed-manifest-file> : $(properties) ]
791        {
792            DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ;
793            msvc.manifest.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ;
794        }
795        else
796        {
797            msvc.manifest $(targets) : $(sources) : $(properties) ;
798        }
799    }
800}
801
802rule link.dll ( targets + : sources * : properties * )
803{
804    set-setup-command $(targets) : $(properties) ;
805    DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
806    local import-lib ;
807    if ! <suppress-import-lib>true in $(properties)
808    {
809        import-lib = $(targets[2]) ;
810        IMPORT_LIB on $(targets) = $(import-lib) ;
811    }
812    # On msvc-14.1, the linker might not touch the import library
813    # if the exports do not change.  (Apparently this could also
814    # happen for incremental linking, which is why we disable it,
815    # but that no longer seems to be enough).
816    # Therefore, don't update the import library just because
817    # it's out-dated.  It will be force updated, when the dll
818    # is updated.  Also, make it so that anything that depends
819    # on it depends on the dll as well.
820    NOUPDATE $(import-lib) ;
821    INCLUDES $(import-lib) : $(targets[1]) ;
822    if <embed-manifest>on in $(properties) && <embed-manifest-via>mt in $(properties)
823    {
824        if [ feature.get-values <embed-manifest-file> : $(properties) ]
825        {
826            DEPENDS $(<) : [ on $(<) return $(EMBED_MANIFEST_FILE) ] ;
827            msvc.manifest.dll.user $(targets) $(EMBED_MANIFEST_FILE) : $(sources) : $(properties) ;
828        }
829        else
830        {
831            msvc.manifest.dll $(targets) : $(sources) : $(properties) ;
832        }
833    }
834}
835
836# Incremental linking a DLL causes no end of problems: if the actual exports do
837# not change, the import .lib file is never updated. Therefore, the .lib is
838# always out-of-date and gets rebuilt every time. I am not sure that incremental
839# linking is such a great idea in general, but in this case I am sure we do not
840# want it.
841
842# Windows manifest is a new way to specify dependencies on managed DotNet
843# assemblies and Windows native DLLs. The manifests are embedded as resources
844# and are useful in any PE target (both DLL and EXE).
845
846{
847    actions link bind DEF_FILE LIBRARIES_MENTIONED_BY_FILE MANIFEST_FILE
848    {
849        $(.SETUP) $(.LD) $(LINKFLAGS) /out:"$(<[1]:W)" /LIBPATH:"$(LINKPATH:W)" /MANIFESTINPUT:"$(MANIFEST_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
850    }
851
852    actions manifest
853    {
854        $(.SETUP) $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);1"
855    }
856
857    actions manifest.user bind EMBED_MANIFEST_FILE
858    {
859        $(.SETUP) $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);1"
860    }
861
862    actions link.dll bind IMPORT_LIB DEF_FILE LIBRARIES_MENTIONED_BY_FILE MANIFEST_FILE
863    {
864        $(.SETUP) $(.LD) /DLL $(LINKFLAGS) /out:"$(<[1]:W)" /IMPLIB:"$(IMPORT_LIB:W)" /LIBPATH:"$(LINKPATH:W)" /def:"$(DEF_FILE)" /MANIFESTINPUT:"$(MANIFEST_FILE)" $(OPTIONS) @"@($(<[1]:W).rsp:E=$(.nl)"$(>)" $(.nl)$(LIBRARIES_MENTIONED_BY_FILE) $(.nl)$(LIBRARIES) $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_ST).lib" $(.nl)"$(LIBRARY_OPTION)$(FINDLIBS_SA).lib")"
865    }
866
867    actions manifest.dll
868    {
869        $(.SETUP) $(.MT) -manifest "$(<[1]).manifest" "-outputresource:$(<[1]);2"
870    }
871
872    actions manifest.dll.user bind EMBED_MANIFEST_FILE
873    {
874        $(.SETUP) $(.MT) -manifest "$(EMBED_MANIFEST_FILE)" "-outputresource:$(<[1]);2"
875    }
876}
877
878# This rule sets up the pdb file that will be used when generating static
879# libraries and the debug-store option is database, so that the compiler puts
880# all the debug info into a single .pdb file named after the library.
881#
882# Poking at source targets this way is probably not clean, but it is the
883# easiest approach.
884#
885rule archive ( targets + : sources * : properties * )
886{
887    set-setup-command $(targets) : $(properties) ;
888    PDB_NAME on $(>) = $(<[1]:S=.pdb) ;
889    LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
890}
891
892
893################################################################################
894#
895# Classes.
896#
897################################################################################
898
899class msvc-pch-generator : pch-generator
900{
901    import property-set ;
902
903    rule run-pch ( project name ? : property-set : sources * )
904    {
905        # Searching for the header and source file in the sources.
906        local pch-header ;
907        local pch-source ;
908        for local s in $(sources)
909        {
910            if [ type.is-derived [ $(s).type ] H ]
911            {
912                pch-header = $(s) ;
913            }
914            else if
915                [ type.is-derived [ $(s).type ] CPP ] ||
916                [ type.is-derived [ $(s).type ] C ]
917            {
918                pch-source = $(s) ;
919            }
920        }
921
922        if ! $(pch-header)
923        {
924            import errors : user-error : errors.user-error ;
925            errors.user-error "can not build pch without pch-header" ;
926        }
927
928        # If we do not have the PCH source - that is fine. We will just create a
929        # temporary .cpp file in the action.
930
931        local generated = [ generator.run $(project) $(name)
932            : [ property-set.create
933                # Passing of <pch-source> is a dirty trick, needed because
934                # non-composing generators with multiple inputs are subtly
935                # broken. For more detailed information see:
936                # https://zigzag.cs.msu.su:7813/boost.build/ticket/111
937                <pch-source>$(pch-source)
938                [ $(property-set).raw ] ]
939            : $(pch-header) ] ;
940
941        local pch-file ;
942        for local g in $(generated[2-])
943        {
944            if [ type.is-derived [ $(g).type ] PCH ]
945            {
946                pch-file = $(g) ;
947            }
948        }
949
950        return [ $(generated[1]).add-raw <pch-header>$(pch-header)
951            <pch-file>$(pch-file) ] $(generated[2-]) ;
952    }
953}
954
955
956################################################################################
957#
958# Local rules.
959#
960################################################################################
961
962# Detects versions listed as '.known-versions' by checking registry information,
963# environment variables & default paths. Supports both native Windows and
964# Cygwin.
965#
966local rule auto-detect-toolset-versions ( )
967{
968    if [ os.name ] in NT CYGWIN
969    {
970        # Get installation paths from the registry.
971        for local i in $(.known-versions)
972        {
973            if $(.version-$(i)-reg)
974            {
975                local vc-path ;
976                for local x in "" "Wow6432Node\\"
977                {
978                    vc-path += [ W32_GETREG
979                        "HKEY_LOCAL_MACHINE\\SOFTWARE\\"$(x)"\\Microsoft\\"$(.version-$(i)-reg)
980                        : "ProductDir" ] ;
981                }
982
983                if $(vc-path)
984                {
985                    vc-path = [ path.join [ path.make-NT $(vc-path[1]) ] "bin" ] ;
986                    register-configuration $(i) : [ path.native $(vc-path[1]) ] ;
987                }
988            }
989        }
990    }
991
992    # Check environment and default installation paths.
993    for local i in $(.known-versions)
994    {
995        if ! $(i) in [ $(.versions).all ]
996        {
997            register-configuration $(i) : [ default-path $(i) ] ;
998        }
999    }
1000}
1001
1002actions write-setup-script
1003{
1004    @($(STDOUT):E=$(FILE_CONTENTS:J=$(.nl))) > "$(<)"
1005}
1006
1007if [ os.name ] = NT
1008{
1009    local rule call-batch-script ( command )
1010    {
1011        return "call $(command) >nul$(.nl)" ;
1012    }
1013}
1014else
1015{
1016    # On cygwin, we need to run both the batch script
1017    # and the following command in the same instance
1018    # of cmd.exe.
1019    local rule call-batch-script ( command )
1020    {
1021        return "cmd.exe /S /C call $(command) \">nul\" \"&&\" " ;
1022    }
1023}
1024
1025# Local helper rule to create the vcvars setup command for given architecture
1026# and options.
1027#
1028local rule generate-setup-cmd ( version : command : parent : options * : cpu : global-setup ? : default-global-setup-options : default-setup )
1029{
1030    local setup-options ;
1031    local setup = [ feature.get-values <setup-$(cpu)> : $(options) ] ;
1032
1033    if ! $(setup)-is-defined
1034    {
1035        if $(global-setup)-is-defined
1036        {
1037            setup = $(global-setup) ;
1038
1039            # If needed we can easily add using configuration flags
1040            # here for overriding which options get passed to the
1041            # global setup command for which target platform:
1042            # setup-options = [ feature.get-values <setup-options-$(c)> : $(options) ] ;
1043            setup-options ?= $(default-global-setup-options) ;
1044        }
1045        else
1046        {
1047            if [ MATCH "(14.2)" : $(version) ]
1048            {
1049                if $(.debug-configuration)
1050                {
1051                    ECHO "notice: [generate-setup-cmd] $(version) is 14.2" ;
1052                }
1053                parent = [ path.native [ path.join  $(parent) "..\\..\\..\\..\\..\\Auxiliary\\Build" ] ] ;
1054            }
1055            else if [ MATCH "(14.1)" : $(version) ]
1056            {
1057                if $(.debug-configuration)
1058                {
1059                    ECHO "notice: [generate-setup-cmd] $(version) is 14.1" ;
1060                }
1061                parent = [ path.native [ path.join  $(parent) "..\\..\\..\\..\\..\\Auxiliary\\Build" ] ] ;
1062            }
1063            setup = [ locate-default-setup $(command) : $(parent) : $(default-setup) ] ;
1064            setup ?= [ path.join  $(parent) "vcvarsall.bat" ] ;
1065        }
1066    }
1067
1068    return $(setup) "$(setup-options:J= )" ;
1069}
1070
1071# Worker for set-setup-command.  Usable in a virtual-target.action.
1072rule adjust-setup-command ( new-setup : setup : properties * )
1073{
1074    local internal = $(new-setup:S=.read) ;
1075    NOTFILE $(internal) ;
1076    local setup-options = [ property.select <msvc.setup-options> : $(properties) ] ;
1077    setup-options = $(setup-options:G=:E=) ;
1078    DEPENDS $(internal) : $(setup) ;
1079    DEPENDS $(new-setup) : $(internal) ;
1080    REBUILDS $(new-setup) : $(internal) ;
1081    msvc.read-setup $(internal) : $(setup) ;
1082    msvc.write-setup-script $(new-setup) : $(setup) ;
1083    __ACTION_RULE__ on $(internal) = msvc.rewrite-setup $(setup) $(setup-options) $(new-setup) ;
1084}
1085
1086# This doesn't actually do anything.  It's merely
1087# used as a trigger for __ACTION_RULE__.
1088actions quietly read-setup { }
1089
1090# Calculates the changes to the environment make by setup-script
1091# Should be used as a callback for __ACTION_RULE__
1092local rule rewrite-setup ( setup-script setup-options new-setup : target : * )
1093{
1094    local setup-path = [ on $(setup-script) return $(LOCATE) $(SEARCH) ] ;
1095    setup-path = $(setup-path[1]) ;
1096    local command = "\"$(setup-script:G=:R=$(setup-path))\" $(setup-options)" ;
1097    local original-vars = [ SPLIT_BY_CHARACTERS [ SHELL set ] : "\n" ] ;
1098    local new-vars = [ SPLIT_BY_CHARACTERS [ SHELL "$(command) >nul && set" ] : "\n" ] ;
1099    local diff-vars = [ set.difference $(new-vars) : $(original-vars) ] ;
1100    if $(diff-vars)
1101    {
1102        FILE_CONTENTS on $(new-setup) = "REM $(command)" "SET "$(diff-vars) ;
1103    }
1104}
1105
1106IMPORT msvc : rewrite-setup : : msvc.rewrite-setup ;
1107
1108# Helper rule to generate a faster alternative to MSVC setup scripts.
1109# We used to call MSVC setup scripts directly in every action, however in
1110# newer MSVC versions (10.0+) they make long-lasting registry queries
1111# which have a significant impact on build time.
1112local rule set-setup-command ( targets * : properties * )
1113{
1114    if ! [ on $(targets) return $(.SETUP) ]
1115    {
1116        local setup-script = [ on $(targets) return $(.SETUP-SCRIPT) ] ;
1117        # If no setup script was given, then we don't need to do anything.
1118        if ! $(setup-script)
1119        {
1120            return ;
1121        }
1122        local setup-options = [ on $(targets) return $(.SETUP-OPTIONS) ] ;
1123        local key = .setup-command-$(setup-script:E=)-$(setup-options:E=) ;
1124        if ! $($(key))
1125        {
1126            properties = [ feature.expand $(properties) ] ;
1127            properties = [ property.select <toolset> <toolset-msvc:version> <architecture> <address-model> <windows-api> <relevant> : $(properties) ] ;
1128            local ps = [ property-set.create $(properties) <msvc.setup-options>$(setup-options) ] ;
1129            local original = [ virtual-target.from-file $(setup-script) : [ path.pwd ] : $(.project) ] ;
1130            local action = [ new non-scanning-action $(original) : msvc.adjust-setup-command : $(ps) ] ;
1131            local new-setup = [ virtual-target.register [ new file-target msvc-setup.bat exact : : $(.project) : $(action) ] ] ;
1132            local command = [ $(new-setup).actualize ] ;
1133            local path = [ on $(command) return $(LOCATE) ] ;
1134            local block-update = $(command:S=.nup) ;
1135            NOUPDATE $(block-update) ;
1136            NOTFILE $(block-update) ;
1137            DEPENDS $(block-update) : $(command) ;
1138            if [ on $(targets) return $(.REWRITE-SETUP) ]
1139            {
1140                ALWAYS $(command) ;
1141            }
1142            $(key) = [ call-batch-script "\"$(command:WG=:R=$(path))\" $(setup-options:E=)" ] $(block-update) ;
1143        }
1144        DEPENDS $(targets) : $($(key)[2]) ;
1145        .SETUP on $(targets) = $($(key)[1]) ;
1146    }
1147}
1148
1149# Worker rule for toolset version configuration. Takes an explicit version id or
1150# nothing in case it should configure the default toolset version (the first
1151# registered one or a new 'default' one in case no toolset versions have been
1152# registered yet).
1153#
1154local rule configure-really ( version ? : options * )
1155{
1156    local command = [ feature.get-values <command> : $(options) ] ;
1157
1158    if ! $(version) && ! $(command)
1159    {
1160        # We were given neither a command, nor a version.
1161        # Take the best registered (i.e. auto-detected) version.
1162        # FIXME: consider whether an explicitly specified setup script
1163        # should disable this logic.  We already won't get here if
1164        # there is a user specified command.
1165        version = [ $(.versions).all ] ;
1166        for local known in $(.known-versions)
1167        {
1168            if $(known) in $(version)
1169            {
1170                version = $(known) ;
1171                break ;
1172            }
1173        }
1174        # version might still have multiple elements if no versions
1175        # were auto-detected, but an unknown version was configured
1176        # manually.
1177        version = $(version[1]) ;
1178    }
1179
1180    # Handle a user-provided command, and deduce the version if necessary.
1181    # If the user-requested version was not autodetected and no command
1182    # was given, attempt to find it in PATH
1183    if $(command) || ! ( $(version:E=default) in [ $(.versions).all ] )
1184    {
1185        local found-command = [ common.get-invocation-command-nodefault msvc : cl.exe : $(command) ] ;
1186
1187        if $(found-command)
1188        {
1189            command = $(found-command) ;
1190            if ! $(command:D)
1191            {
1192                local path = [ common.get-absolute-tool-path $(command) ] ;
1193                command = $(command:R=$(path)) ;
1194            }
1195        }
1196        else
1197        {
1198            # If we still failed to find cl.exe, bail out.
1199            ECHO ;
1200            ECHO warning\:
1201                "Did not find command for MSVC toolset."
1202                "If you have Visual Studio 2017 installed you will need to"
1203                "specify the full path to the command,"
1204                "set VS150COMNTOOLS for your installation,"
1205                "or"
1206                "build from the 'Visual Studio Command Prompt for VS 2017'."
1207                ;
1208            ECHO ;
1209            command ?= cl.exe ;
1210        }
1211
1212        if ! $(version)
1213        {
1214            # Even if version is not explicitly specified, try to detect the
1215            # version from the path.
1216            # FIXME: We currently detect both Microsoft Visual Studio 9.0 and
1217            # 9.0express as 9.0 here.
1218            if [ MATCH "(MSVC\\\\14.2)" : $(command) ]
1219            {
1220                version = 14.2 ;
1221            }
1222            else if [ MATCH "(MSVC\\\\14.1)" : $(command) ]
1223            {
1224                version = 14.1 ;
1225            }
1226            else if [ MATCH "(Microsoft Visual Studio 14)" : $(command) ]
1227            {
1228                version = 14.0 ;
1229            }
1230            else if [ MATCH "(Microsoft Visual Studio 12)" : $(command) ]
1231            {
1232                version = 12.0 ;
1233            }
1234            else if [ MATCH "(Microsoft Visual Studio 11)" : $(command) ]
1235            {
1236                version = 11.0 ;
1237            }
1238            else if [ MATCH "(Microsoft Visual Studio 10)" : $(command) ]
1239            {
1240                version = 10.0 ;
1241            }
1242            else if [ MATCH "(Microsoft Visual Studio 9)" : $(command) ]
1243            {
1244                version = 9.0 ;
1245            }
1246            else if [ MATCH "(Microsoft Visual Studio 8)" : $(command) ]
1247            {
1248                version = 8.0 ;
1249            }
1250            else if [ MATCH "(NET 2003[\/\\]VC7)" : $(command) ]
1251            {
1252                version = 7.1 ;
1253            }
1254            else if [ MATCH "(Microsoft Visual C\\+\\+ Toolkit 2003)" :
1255                $(command) ]
1256            {
1257                version = 7.1toolkit ;
1258            }
1259            else if [ MATCH "(.NET[\/\\]VC7)" : $(command) ]
1260            {
1261                version = 7.0 ;
1262            }
1263            else
1264            {
1265                version = 6.0 ;
1266            }
1267        }
1268    }
1269
1270    # Version alias -> real version number.
1271    version = [ resolve-possible-msvc-version-alias $(version) ] ;
1272
1273    # Check whether the selected configuration is already in use.
1274    if $(version) in [ $(.versions).used ]
1275    {
1276        # Allow multiple 'toolset.using' calls for the same configuration if the
1277        # identical sets of options are used.
1278        if $(options) && ( $(options) != [ $(.versions).get $(version) : options ] )
1279        {
1280            import errors ;
1281            errors.user-error "MSVC toolset configuration: Toolset version"
1282                "'$(version)' already configured." ;
1283        }
1284    }
1285    else
1286    {
1287        # Register a new configuration.
1288        $(.versions).register $(version) ;
1289        $(.versions).set $(version) : options : $(options) ;
1290
1291        # Mark the configuration as 'used'.
1292        $(.versions).use $(version) ;
1293
1294        # Generate conditions and save them.
1295        local conditions = [ common.check-init-parameters msvc : version $(version) ] ;
1296
1297        $(.versions).set $(version) : conditions : $(conditions) ;
1298
1299        command ?= [ $(.versions).get $(version) : default-command ] ;
1300
1301        # For 14.1+ we need the exact version as MS is planning rolling updates
1302        # that will cause our `setup-cmd` to become invalid
1303        exact-version = [ MATCH "(14\.[1-9][0-9]\.[0-9\.]+)" : $(command) ] ;
1304
1305        common.handle-options msvc : $(conditions) : $(command) : $(options) ;
1306
1307        # Generate and register setup command.
1308
1309        local below-8.0 = [ MATCH "^([67]\\.)" : $(version) ] ;
1310        local below-11.0 = [ MATCH "^([6789]\\.|10\\.)" : $(version) ] ;
1311
1312        local cpu = i386 amd64 ia64 arm arm64 ;
1313        if $(below-8.0)
1314        {
1315            cpu = i386 ;
1316        }
1317        else if $(below-11.0)
1318        {
1319            cpu = i386 amd64 ia64 ;
1320        }
1321
1322        local setup-amd64 ;
1323        local setup-i386 ;
1324        local setup-ia64 ;
1325        local setup-arm ;
1326        local setup-arm64 ;
1327        local setup-phone-i386 ;
1328        local setup-phone-arm ;
1329
1330        if $(command)
1331        {
1332            # TODO: Note that if we specify a non-existant toolset version then
1333            # this rule may find and use a corresponding compiler executable
1334            # belonging to an incorrect toolset version. For example, if you
1335            # have only MSVC 7.1 installed, have its executable on the path and
1336            # specify you want Boost Build to use MSVC 9.0, then you want Boost
1337            # Build to report an error but this may cause it to silently use the
1338            # MSVC 7.1 compiler even though it thinks it is using the msvc-9.0
1339            # toolset version.
1340            command = [ common.get-absolute-tool-path $(command[-1]) ] ;
1341        }
1342
1343        if $(command)
1344        {
1345            local parent = [ path.make $(command) ] ;
1346            parent = [ path.parent $(parent) ] ;
1347            parent = [ path.native $(parent) ] ;
1348
1349            # Setup will be used if the command name has been specified. If
1350            # setup is not specified explicitly then a default setup script will
1351            # be used instead. Setup scripts may be global or architecture/
1352            # /platform/cpu specific. Setup options are used only in case of
1353            # global setup scripts.
1354
1355            # Default setup scripts provided with different VC distributions:
1356            #
1357            #   VC 7.1 had only the vcvars32.bat script specific to 32 bit i386
1358            # builds. It was located in the bin folder for the regular version
1359            # and in the root folder for the free VC 7.1 tools.
1360            #
1361            #   Later 8.0 & 9.0 versions introduce separate platform specific
1362            # vcvars*.bat scripts (e.g. 32 bit, 64 bit AMD or 64 bit Itanium)
1363            # located in or under the bin folder. Most also include a global
1364            # vcvarsall.bat helper script located in the root folder which runs
1365            # one of the aforementioned vcvars*.bat scripts based on the options
1366            # passed to it. So far only the version coming with some PlatformSDK
1367            # distributions does not include this top level script but to
1368            # support those we need to fall back to using the worker scripts
1369            # directly in case the top level script can not be found.
1370
1371            local global-setup = [ feature.get-values <setup> : $(options) ] ;
1372            global-setup = $(global-setup[1]) ;
1373            local global-setup-phone = $(global-setup) ;
1374            if ! $(below-8.0)
1375            {
1376                global-setup ?= [ locate-default-setup $(command) : $(parent) :
1377                    vcvarsall.bat ] ;
1378            }
1379
1380            local default-setup-amd64 = vcvarsx86_amd64.bat ;
1381            local default-setup-i386  = vcvars32.bat ;
1382            local default-setup-ia64  = vcvarsx86_ia64.bat ;
1383            local default-setup-arm   = vcvarsx86_arm.bat ;
1384            local default-setup-arm64 = vcvarsx86_arm64.bat ;
1385            local default-setup-phone-i386 = vcvarsphonex86.bat ;
1386            local default-setup-phone-arm = vcvarsphonex86_arm.bat ;
1387
1388            # http://msdn2.microsoft.com/en-us/library/x4d2c09s(VS.80).aspx and
1389            # http://msdn2.microsoft.com/en-us/library/x4d2c09s(vs.90).aspx
1390            # mention an x86_IPF option, that seems to be a documentation bug
1391            # and x86_ia64 is the correct option.
1392            local default-global-setup-options-amd64 = x86_amd64 ;
1393            local default-global-setup-options-i386  = x86 ;
1394            local default-global-setup-options-ia64  = x86_ia64 ;
1395            local default-global-setup-options-arm   = x86_arm ;
1396            local default-global-setup-options-arm64 = x86_arm64 ;
1397
1398            # When using 64-bit Windows, and targeting 64-bit, it is possible to
1399            # use a native 64-bit compiler, selected by the "amd64" & "ia64"
1400            # parameters to vcvarsall.bat. There are two variables we can use --
1401            # PROCESSOR_ARCHITECTURE and PROCESSOR_IDENTIFIER. The first is
1402            # 'x86' when running 32-bit Windows, no matter which processor is
1403            # used, and 'AMD64' on 64-bit windows on x86 (either AMD64 or EM64T)
1404            # Windows.
1405            #
1406            if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITECTURE ] ]
1407            {
1408                default-global-setup-options-amd64 = amd64 ;
1409            }
1410            # When B2 itself is running as a 32-bit process on 64-bit
1411            # Windows, the above test will fail (since WOW64 simulates a 32-bit
1412            # environment, including environment values).  So check the WOW64
1413            # variable PROCESSOR_ARCHITEW6432 as well.
1414            if [ MATCH ^(AMD64) : [ os.environ PROCESSOR_ARCHITEW6432 ] ]
1415            {
1416                default-global-setup-options-amd64 = amd64 ;
1417            }
1418            # TODO: The same 'native compiler usage' should be implemented for
1419            # the Itanium platform by using the "ia64" parameter. For this
1420            # though we need someone with access to this platform who can find
1421            # out how to correctly detect this case.
1422            else if $(somehow-detect-the-itanium-platform)
1423            {
1424                default-global-setup-options-ia64 = ia64 ;
1425            }
1426
1427            for local c in $(cpu)
1428            {
1429                exact-version ?= $(version) ;
1430                setup-$(c) = [ generate-setup-cmd $(exact-version) : $(command) : $(parent) : $(options) : $(c) : $(global-setup) : $(default-global-setup-options-$(c)) : $(default-setup-$(c)) ] ;
1431            }
1432
1433            # Windows phone has different setup scripts, located in a different directory hierarchy.
1434            # The 11.0 toolset can target Windows Phone 8.0 and the 12.0 toolset can target Windows Phone 8.1,
1435            # each of which have a different directory for their vcvars setup scripts.
1436            local phone-parent = [ path.native [ path.join $(parent) WPSDK ] ] ;
1437            local phone-directory = $(phone-parent) ;
1438            if [ MATCH "(11.0)" : $(version) ]
1439            {
1440                phone-directory = [ path.native [ path.join $(phone-directory) WP80 ] ] ;
1441            }
1442            else if [ MATCH "(12.0)" : $(version) ]
1443            {
1444                phone-directory = [ path.native [ path.join $(phone-directory) WP81 ] ] ;
1445            }
1446            global-setup-phone ?= [ locate-default-setup $(phone-directory) : $(phone-parent) : vcvarsphoneall.bat ] ;
1447
1448            # If can't locate default phone setup script then this VS version doesn't support Windows Phone.
1449            if $(global-setup-phone)-is-defined
1450            {
1451                # i386 CPU is for the Windows Phone emulator in Visual Studio.
1452                local phone-cpu = i386 arm ;
1453                for local c in $(phone-cpu)
1454                {
1455                    setup-phone-$(c) = [ generate-setup-cmd $(version) : $(phone-directory) : $(phone-parent) : $(options) : $(c) : $(global-setup-phone) : $(default-global-setup-options-$(c)) : $(default-setup-phone-$(c)) ] ;
1456                }
1457            }
1458        }
1459
1460        # Get tool names (if any) and finish setup.
1461
1462        compiler = [ feature.get-values <compiler> : $(options) ] ;
1463        compiler ?= cl ;
1464
1465        linker = [ feature.get-values <linker> : $(options) ] ;
1466        linker ?= link ;
1467
1468        resource-compiler = [ feature.get-values <resource-compiler> : $(options) ] ;
1469        resource-compiler ?= rc ;
1470
1471        # Turn on some options for i386 assembler
1472        #  -coff  generate COFF format object file (compatible with cl.exe output)
1473        local default-assembler-amd64 = ml64 ;
1474        local default-assembler-i386  = "ml -coff" ;
1475        local default-assembler-ia64  = ias ;
1476        local default-assembler-arm   = armasm ;
1477        local default-assembler-arm64 = armasm64 ;
1478
1479        # For the assembler the following options are turned on by default:
1480        #
1481        #   -Zp4   align structures to 4 bytes
1482        #   -Cp    preserve case of user identifiers
1483        #   -Cx    preserve case in publics, externs
1484        #
1485        local assembler-flags-amd64 = "-c -Zp4 -Cp -Cx" ;
1486        local assembler-flags-i386  = "-c -Zp4 -Cp -Cx" ;
1487        local assembler-flags-ia64  = "-c -Zp4 -Cp -Cx" ;
1488        local assembler-flags-arm   = "" ;
1489        local assembler-flags-arm64 = "" ;
1490
1491        local assembler-output-flag-amd64 = -Fo ;
1492        local assembler-output-flag-i386  = -Fo ;
1493        local assembler-output-flag-ia64  = -Fo ;
1494        local assembler-output-flag-arm   = -o ;
1495        local assembler-output-flag-arm64 = -o ;
1496
1497        assembler = [ feature.get-values <assembler> : $(options) ] ;
1498
1499        idl-compiler = [ feature.get-values <idl-compiler> : $(options) ] ;
1500        idl-compiler ?= midl ;
1501
1502        mc-compiler = [ feature.get-values <mc-compiler> : $(options) ] ;
1503        mc-compiler ?= mc ;
1504
1505        manifest-tool = [ feature.get-values <manifest-tool> : $(options) ] ;
1506        manifest-tool ?= mt ;
1507
1508        local cc-filter = [ feature.get-values <compiler-filter> : $(options) ]
1509            ;
1510
1511        for local c in $(cpu)
1512        {
1513            # Setup script is not required in some configurations.
1514            setup-$(c) ?= "" ;
1515
1516            local cpu-conditions = $(conditions)/$(.cpu-arch-$(c)) ;
1517
1518            if $(.debug-configuration)
1519            {
1520                for local cpu-condition in $(cpu-conditions)
1521                {
1522                    ECHO "notice: [msvc-cfg] condition: '$(cpu-condition)', setup: '$(setup-$(c):J= )'" ;
1523                }
1524            }
1525
1526            local cpu-assembler = $(assembler) ;
1527            cpu-assembler ?= $(default-assembler-$(c)) ;
1528            local assembler-flags = $(assembler-flags-$(c)) ;
1529            local assembler-output-flag = $(assembler-output-flag-$(c)) ;
1530
1531            for local api in desktop store phone
1532            {
1533                local setup-script = $(setup-$(c)) ;
1534                if $(api) = phone
1535                {
1536                    setup-script = $(setup-phone-$(c)) ;
1537                }
1538
1539                if <rewrite-setup-scripts>always in $(options)
1540                {
1541                    toolset.flags msvc .REWRITE-SETUP <windows-api>$(api)/$(cpu-conditions) : true ;
1542                }
1543
1544                if ! $(setup-script)
1545                {
1546                    # Should we try to set up some error handling or fallbacks here?
1547                }
1548                else if <rewrite-setup-scripts>off in $(options) || [ os.name ] != NT
1549                {
1550                    toolset.flags msvc .SETUP <windows-api>$(api)/$(cpu-conditions) : [ call-batch-script "\"$(setup-script[1]:W)\" $(setup-script[2-]:E=)" ] ;
1551                }
1552                else
1553                {
1554                    toolset.flags msvc .SETUP-SCRIPT <windows-api>$(api)/$(cpu-conditions) : $(setup-script[1]) ;
1555                    toolset.flags msvc .SETUP-OPTIONS <windows-api>$(api)/$(cpu-conditions) : $(setup-script[2-]) ;
1556                }
1557
1558                toolset.flags msvc.compile .RC  <windows-api>$(api)/$(cpu-conditions) : $(resource-compiler) ;
1559                toolset.flags msvc.compile .IDL <windows-api>$(api)/$(cpu-conditions) : $(idl-compiler) ;
1560                toolset.flags msvc.compile .MC  <windows-api>$(api)/$(cpu-conditions) : $(mc-compiler) ;
1561                toolset.flags msvc.link    .MT  <windows-api>$(api)/$(cpu-conditions) : $(manifest-tool) -nologo ;
1562
1563                if $(api) = desktop
1564                {
1565                    toolset.flags msvc.compile .CC  <windows-api>$(api)/$(cpu-conditions) : $(compiler) /Zm800 -nologo ;
1566                }
1567                else
1568                {
1569                    toolset.flags msvc.compile .CC  <windows-api>$(api)/$(cpu-conditions) : $(compiler) /Zm800 /ZW /EHsc -nologo ;
1570                }
1571                toolset.flags msvc.compile .ASM <windows-api>$(api)/$(cpu-conditions) : $(cpu-assembler) $(assembler-flags) -nologo ;
1572                toolset.flags msvc.compile .ASM_OUTPUT <windows-api>$(api)/$(cpu-conditions) : $(assembler-output-flag) ;
1573                toolset.flags msvc.link    .LD  <windows-api>$(api)/$(cpu-conditions) : $(linker) /NOLOGO "/INCREMENTAL:NO" ;
1574                toolset.flags msvc.archive .LD  <windows-api>$(api)/$(cpu-conditions) : $(linker) /lib /NOLOGO  ;
1575            }
1576
1577            if $(cc-filter)
1578            {
1579                toolset.flags msvc .CC.FILTER $(cpu-conditions) : "|" $(cc-filter) ;
1580            }
1581        }
1582
1583        # Starting with Visual Studio 2013 the CRT is split into a desktop and app dll.
1584        # If targeting WinRT and 12.0 set lib path to link against app CRT.
1585        if [ MATCH "(12)" : $(version) ]
1586        {
1587            local storeLibPath = [ path.join $(parent) "lib/store" ] ;
1588            toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-i386) : [ path.native $(storeLibPath) ] ;
1589            toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-amd64) : [ path.native [ path.join $(storeLibPath) "amd64" ] ] ;
1590            toolset.flags msvc.link LINKPATH $(conditions)/<windows-api>store/$(.cpu-arch-arm) : [ path.native [ path.join $(storeLibPath) "arm" ] ] ;
1591        }
1592
1593        # LTO
1594        toolset.flags msvc.compile OPTIONS $(conditions)/<lto>on : /GL ;
1595        toolset.flags msvc.link OPTIONS $(conditions)/<lto>on : /LTCG ;
1596
1597        # Set version-specific flags.
1598        configure-version-specific msvc : $(version) : $(conditions) ;
1599    }
1600}
1601
1602
1603# Returns the default installation path for the given version.
1604#
1605local rule default-path ( version )
1606{
1607    local result ;
1608    {
1609        # try to use vswhere
1610        local pseudo_env_VSCOMNTOOLS ;
1611        local all-env-paths ;
1612        local root = [ os.environ "ProgramFiles(x86)" ] ;
1613        if ( ! $(root) )
1614        {
1615            root = [ os.environ "ProgramFiles" ] ;
1616        }
1617        if ( ! $(root) ) && [ os.name ] in CYGWIN
1618        {
1619            # We probably are in an 'env -i' Cygwin session, where the user
1620            # was unable restore the "ProgramFiles(x86)" environment variable,
1621            # because it is an invalid environment variable name in Cygwin.
1622            # However, we can try to query cygpath instead.
1623            root = [ SHELL "cygpath -w -F 42" : strip-eol ] ; # CSIDL_PROGRAM_FILESX86
1624            if ( ! $(root) )
1625            {
1626                root = [ SHELL "cygpath -w -F 38" : strip-eol ] ; # CSIDL_PROGRAM_FILES
1627            }
1628        }
1629        # When we are a Cygwin build, [ SHELL ] does execute using "/bin/sh -c".
1630        # When /bin/sh does find a forward slash, no PATH search is performed,
1631        # causing [ SHELL "C:\\...\\Installer/vswhere.exe" ] to succeed.
1632        # And fortunately, forward slashes do also work in native Windows.
1633        local vswhere = "$(root)/Microsoft Visual Studio/Installer/vswhere.exe" ;
1634        # The check for $(root) is to avoid a segmentation fault if not found.
1635        if $(version) in 14.1 14.2 default && $(root) && [ path.exists $(vswhere) ]
1636        {
1637            local req = "-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64" ;
1638            local prop = "-property installationPath" ;
1639            local limit ;
1640
1641            if $(version) = 14.2 || $(version) = "default"
1642            {
1643                limit = "-version \"[16.0,17.0)\"" ;
1644            }
1645            else if $(version) = 14.1
1646            {
1647                limit = "-version \"[15.0,16.0)\"" ;
1648            }
1649
1650            # Quoting the "*" is for when we are a Cygwin build, to bypass /bin/sh.
1651            local vswhere_cmd = "\"$(vswhere)\" -latest -products \"*\" $(req) $(prop) $(limit)" ;
1652            # The split character "\r" is for when we are a Cygwin build.
1653            local shell_ret = [ SPLIT_BY_CHARACTERS [ SHELL $(vswhere_cmd) ] : "\r\n" ] ;
1654            pseudo_env_VSCOMNTOOLS = [ path.native [ path.join $(shell_ret) "\\Common7\\Tools" ] ] ;
1655            if ! [ path.exists $(pseudo_env_VSCOMNTOOLS) ]
1656            {
1657                return ; # Not found.  If we have vswhere, assume that it works.
1658            }
1659            all-env-paths = $(pseudo_env_VSCOMNTOOLS) ;
1660        }
1661        else
1662        {
1663            all-env-paths = [ sequence.transform os.environ
1664                : $(.version-$(version)-env) ] ;
1665        }
1666
1667        # Check environment or previous path_VS150
1668        for local env-path in $(all-env-paths)
1669        {
1670            if $(env-path) && $(.version-$(version)-path)
1671            {
1672                for local bin-path in $(.version-$(version)-path)
1673                {
1674                    result = [ path.glob [ path.make $(env-path) ] : $(bin-path) ] ;
1675                    if $(result)
1676                    {
1677                        result = [ path.native $(result[1]) ] ;
1678                        break ;
1679                    }
1680                }
1681            }
1682            if $(result)
1683            {
1684                break ;
1685            }
1686        }
1687    }
1688
1689    return $(result) ;
1690}
1691
1692
1693
1694rule get-rspline ( target : lang-opt )
1695{
1696    CC_RSPLINE on $(target) = [ on $(target) return $(lang-opt) -U$(UNDEFS)
1697        $(CFLAGS) $(C++FLAGS) $(OPTIONS) -c $(.nl)-D$(DEFINES)
1698        $(.nl)\"-I$(INCLUDES:W)\" $(.nl)\"-FI$(FORCE_INCLUDES:W)\" ] ;
1699}
1700
1701class msvc-linking-generator : linking-generator
1702{
1703    # Calls the base version.  If necessary, also create a target for the
1704    # manifest file.specifying source's name as the name of the created
1705    # target. As result, the PCH will be named whatever.hpp.gch, and not
1706    # whatever.gch.
1707    rule generated-targets ( sources + : property-set : project name ? )
1708    {
1709        local result = [ linking-generator.generated-targets $(sources)
1710          : $(property-set) : $(project) $(name) ] ;
1711
1712        if $(result)
1713        {
1714            local name-main = [ $(result[1]).name ] ;
1715            local action = [ $(result[1]).action ] ;
1716
1717            if [ $(property-set).get <debug-symbols> ] = "on"
1718            {
1719                # We force the exact name on PDB. The reason is tagging -- the
1720                # tag rule may reasonably special case some target types, like
1721                # SHARED_LIB. The tag rule will not catch PDBs, and it cannot
1722                # even easily figure out if a PDB is paired with a SHARED_LIB,
1723                # EXE or something else. Because PDBs always get the same name
1724                # as the main target, with .pdb as extension, just force it.
1725                local target = [ class.new file-target $(name-main:S=.pdb) exact
1726                    : PDB : $(project) : $(action) ] ;
1727                local registered-target = [ virtual-target.register $(target) ]
1728                    ;
1729                if $(target) != $(registered-target)
1730                {
1731                    $(action).replace-targets $(target) : $(registered-target) ;
1732                }
1733                result += $(registered-target) ;
1734            }
1735
1736            if [ $(property-set).get <embed-manifest> ] = "off"
1737            {
1738                # Manifest is an evil target. It has .manifest appened to the
1739                # name of the main target, including extension, e.g.
1740                # a.exe.manifest. We use the 'exact' name to achieve this
1741                # effect.
1742                local target = [ class.new file-target $(name-main).manifest
1743                    exact : MANIFEST : $(project) : $(action) ] ;
1744                local registered-target = [ virtual-target.register $(target) ]
1745                    ;
1746                if $(target) != $(registered-target)
1747                {
1748                    $(action).replace-targets $(target) : $(registered-target) ;
1749                }
1750                result += $(registered-target) ;
1751            }
1752        }
1753        return $(result) ;
1754    }
1755}
1756
1757
1758# Unsafe worker rule for the register-toolset() rule. Must not be called
1759# multiple times.
1760#
1761local rule register-toolset-really ( )
1762{
1763    feature.extend toolset : msvc ;
1764
1765    # Intel and msvc supposedly have link-compatible objects.
1766    feature.subfeature toolset msvc : vendor : intel : propagated optional ;
1767
1768    # Inherit MIDL flags.
1769    toolset.inherit-flags msvc : midl ;
1770
1771    # Inherit MC flags.
1772    toolset.inherit-flags msvc : mc ;
1773
1774    # Dynamic runtime comes only in MT flavour.
1775    toolset.add-requirements
1776        <toolset>msvc,<runtime-link>shared:<threading>multi ;
1777
1778    # Declare msvc toolset specific features.
1779    {
1780        feature.feature debug-store : object database : propagated ;
1781        feature.feature pch-source  :                 : dependency free ;
1782    }
1783
1784    # Declare generators.
1785    {
1786        # TODO: Is it possible to combine these? Make the generators
1787        # non-composing so that they do not convert each source into a separate
1788        # .rsp file.
1789        generators.register [ new msvc-linking-generator msvc.link :
1790            OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : EXE : <toolset>msvc ] ;
1791        generators.register [ new msvc-linking-generator msvc.link.dll :
1792            OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB IMPORT_LIB :
1793            <toolset>msvc <suppress-import-lib>false ] ;
1794        generators.register [ new msvc-linking-generator msvc.link.dll :
1795            OBJ SEARCHED_LIB STATIC_LIB IMPORT_LIB : SHARED_LIB :
1796            <toolset>msvc <suppress-import-lib>true ] ;
1797
1798        generators.register-archiver msvc.archive : OBJ : STATIC_LIB : <toolset>msvc ;
1799        generators.register-c-compiler msvc.compile.c++ : CPP : OBJ : <toolset>msvc ;
1800        generators.register-c-compiler msvc.compile.c : C : OBJ : <toolset>msvc ;
1801        generators.register-c-compiler msvc.compile.c++.preprocess : CPP : PREPROCESSED_CPP : <toolset>msvc ;
1802        generators.register-c-compiler msvc.compile.c.preprocess : C : PREPROCESSED_C : <toolset>msvc ;
1803
1804        # Using 'register-c-compiler' adds the build directory to INCLUDES.
1805        generators.register-c-compiler msvc.compile.rc : RC : OBJ(%_res) : <toolset>msvc ;
1806        generators.override msvc.compile.rc : rc.compile.resource ;
1807        generators.register-standard msvc.compile.asm : ASM : OBJ : <toolset>msvc ;
1808
1809        generators.register-c-compiler msvc.compile.idl : IDL : MSTYPELIB H C(%_i) C(%_proxy) C(%_dlldata) : <toolset>msvc ;
1810        generators.override msvc.compile.idl : midl.compile.idl ;
1811
1812        generators.register-standard msvc.compile.mc : MC : H RC : <toolset>msvc ;
1813        generators.override msvc.compile.mc : mc.compile ;
1814
1815        # Note: the 'H' source type will catch both '.h' and '.hpp' headers as
1816        # the latter have their HPP type derived from H. The type of compilation
1817        # is determined entirely by the destination type.
1818        generators.register [ new msvc-pch-generator msvc.compile.c.pch   : H :   C_PCH OBJ : <pch>on <toolset>msvc ] ;
1819        generators.register [ new msvc-pch-generator msvc.compile.c++.pch : H : CPP_PCH OBJ : <pch>on <toolset>msvc ] ;
1820
1821        generators.override msvc.compile.c.pch   : pch.default-c-pch-generator ;
1822        generators.override msvc.compile.c++.pch : pch.default-cpp-pch-generator ;
1823    }
1824
1825    toolset.flags msvc.compile PCH_FILE   <pch>on : <pch-file>   ;
1826    toolset.flags msvc.compile PCH_SOURCE <pch>on : <pch-source> ;
1827    toolset.flags msvc.compile PCH_HEADER <pch>on : <pch-header> ;
1828
1829    #
1830    # Declare flags for compilation.
1831    #
1832
1833    toolset.flags msvc.compile CFLAGS <optimization>speed : /O2 ;
1834    toolset.flags msvc.compile CFLAGS <optimization>space : /O1 ;
1835
1836    toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium) : /G1 ;
1837    toolset.flags msvc.compile CFLAGS $(.cpu-arch-ia64)/<instruction-set>$(.cpu-type-itanium2) : /G2 ;
1838
1839    toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>object : /Z7 ;
1840    toolset.flags msvc.compile CFLAGS <debug-symbols>on/<debug-store>database : /Zi ;
1841    toolset.flags msvc.compile CFLAGS <optimization>off : /Od ;
1842    toolset.flags msvc.compile CFLAGS <inlining>off : /Ob0 ;
1843    toolset.flags msvc.compile CFLAGS <inlining>on : /Ob1 ;
1844    toolset.flags msvc.compile CFLAGS <inlining>full : /Ob2 ;
1845
1846    toolset.flags msvc.compile CFLAGS <warnings>on : /W3 ;
1847    toolset.flags msvc.compile CFLAGS <warnings>off : /W0 ;
1848    toolset.flags msvc.compile CFLAGS <warnings>all : /W4 ;
1849    toolset.flags msvc.compile CFLAGS <warnings>extra : /W4 ;
1850    toolset.flags msvc.compile CFLAGS <warnings>pedantic : /W4 ;
1851    toolset.flags msvc.compile CFLAGS <warnings-as-errors>on : /WX ;
1852
1853    toolset.flags msvc.compile C++FLAGS  <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>off : /EHs ;
1854    toolset.flags msvc.compile C++FLAGS  <exception-handling>on/<asynch-exceptions>off/<extern-c-nothrow>on : /EHsc ;
1855    toolset.flags msvc.compile C++FLAGS  <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>off : /EHa ;
1856    toolset.flags msvc.compile C++FLAGS  <exception-handling>on/<asynch-exceptions>on/<extern-c-nothrow>on : /EHac ;
1857
1858    toolset.flags msvc.compile C++FLAGS  <cxxstd>14 : "/std:c++14" ;
1859    toolset.flags msvc.compile C++FLAGS  <cxxstd>17 : "/std:c++17" ;
1860    toolset.flags msvc.compile C++FLAGS  <cxxstd>latest : "/std:c++latest" ;
1861
1862    # By default 8.0 enables rtti support while prior versions disabled it. We
1863    # simply enable or disable it explicitly so we do not have to depend on this
1864    # default behaviour.
1865    toolset.flags msvc.compile CFLAGS <rtti>on : /GR ;
1866    toolset.flags msvc.compile CFLAGS <rtti>off : /GR- ;
1867    toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>shared : /MD ;
1868    toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>shared : /MDd ;
1869
1870    toolset.flags msvc.compile CFLAGS <runtime-debugging>off/<runtime-link>static/<threading>multi : /MT ;
1871    toolset.flags msvc.compile CFLAGS <runtime-debugging>on/<runtime-link>static/<threading>multi : /MTd ;
1872
1873    toolset.flags msvc.compile OPTIONS <cflags> : ;
1874    toolset.flags msvc.compile.c++ OPTIONS <cxxflags> : ;
1875
1876    toolset.flags msvc.compile PDB_CFLAG <debug-symbols>on/<debug-store>database : /Fd ;
1877
1878    toolset.flags msvc.compile DEFINES <define> ;
1879    toolset.flags msvc.compile UNDEFS <undef> ;
1880    toolset.flags msvc.compile INCLUDES <include> ;
1881    toolset.flags msvc.compile FORCE_INCLUDES <force-include> ;
1882
1883    # Declare flags for the assembler.
1884    toolset.flags msvc.compile.asm USER_ASMFLAGS <asmflags> ;
1885
1886    toolset.flags msvc.compile.asm ASMFLAGS <architecture>x86/<debug-symbols>on : "/Zi /Zd" ;
1887
1888    toolset.flags msvc.compile.asm ASMFLAGS <architecture>x86/<warnings>on : /W3 ;
1889    toolset.flags msvc.compile.asm ASMFLAGS <architecture>x86/<warnings>off : /W0 ;
1890    toolset.flags msvc.compile.asm ASMFLAGS <architecture>x86/<warnings>all : /W4 ;
1891    toolset.flags msvc.compile.asm ASMFLAGS <architecture>x86/<warnings-as-errors>on : /WX ;
1892
1893    toolset.flags msvc.compile.asm ASMDEFINES <architecture>x86 : <define> ;
1894
1895    # Declare flags for linking.
1896    {
1897        toolset.flags msvc.link PDB_LINKFLAG <debug-symbols>on/<debug-store>database : "/PDB:" ;  # not used yet
1898        toolset.flags msvc.link LINKFLAGS <debug-symbols>on : /DEBUG ;
1899        toolset.flags msvc.link DEF_FILE <def-file> ;
1900        toolset.flags msvc.link MANIFEST_FILE <embed-manifest-via>linker : <embed-manifest-file> ;
1901
1902        # The linker disables the default optimizations when using /DEBUG so we
1903        # have to enable them manually for release builds with debug symbols.
1904        toolset.flags msvc LINKFLAGS <debug-symbols>on/<runtime-debugging>off : "/OPT:REF,ICF" ;
1905
1906        toolset.flags msvc LINKFLAGS <user-interface>console : "/subsystem:console" ;
1907        toolset.flags msvc LINKFLAGS <user-interface>gui : "/subsystem:windows" ;
1908        toolset.flags msvc LINKFLAGS <user-interface>wince : "/subsystem:windowsce" ;
1909        toolset.flags msvc LINKFLAGS <user-interface>native : "/subsystem:native" ;
1910        toolset.flags msvc LINKFLAGS <user-interface>auto : "/subsystem:posix" ;
1911
1912        toolset.flags msvc.link OPTIONS <linkflags> ;
1913        toolset.flags msvc.link LINKPATH <library-path> ;
1914
1915        toolset.flags msvc.link FINDLIBS_ST <find-static-library> ;
1916        toolset.flags msvc.link FINDLIBS_SA <find-shared-library> ;
1917        toolset.flags msvc.link LIBRARY_OPTION <toolset>msvc : "" : unchecked ;
1918        toolset.flags msvc.link LIBRARIES_MENTIONED_BY_FILE : <library-file> ;
1919
1920        toolset.flags msvc.link.dll LINKFLAGS <suppress-import-lib>true : /NOENTRY ;
1921    }
1922
1923    toolset.flags msvc.archive AROPTIONS <archiveflags> ;
1924
1925    # Create a project to allow building the setup scripts
1926    project.initialize $(__name__) ;
1927    .project = [ project.current ] ;
1928    project msvc ;
1929
1930    feature.feature msvc.setup-options : : free ;
1931}
1932
1933
1934# Locates the requested setup script under the given folder and returns its full
1935# path or nothing in case the script can not be found. In case multiple scripts
1936# are found only the first one is returned.
1937#
1938# TODO: There used to exist a code comment for the msvc.init rule stating that
1939# we do not correctly detect the location of the vcvars32.bat setup script for
1940# the free VC7.1 tools in case user explicitly provides a path. This should be
1941# tested or simply remove this whole comment in case this toolset version is no
1942# longer important.
1943#
1944local rule locate-default-setup ( command : parent : setup-name )
1945{
1946    local result = [ GLOB $(command) $(parent) : $(setup-name) ] ;
1947    if $(result[1])
1948    {
1949        return $(result[1]) ;
1950    }
1951}
1952
1953
1954# Validates given path, registers found configuration and prints debug
1955# information about it.
1956#
1957local rule register-configuration ( version : path ? )
1958{
1959    if $(path)
1960    {
1961        local command = [ GLOB $(path) : cl.exe ] ;
1962
1963        if $(command)
1964        {
1965            if $(.debug-configuration)
1966            {
1967                ECHO notice\: "[msvc-cfg]" msvc-$(version) detected, command\:
1968                    '$(command)' ;
1969            }
1970
1971            $(.versions).register $(version) ;
1972            $(.versions).set $(version) : default-command : $(command) ;
1973        }
1974    }
1975}
1976
1977
1978################################################################################
1979#
1980#   Startup code executed when loading this module.
1981#
1982################################################################################
1983
1984if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
1985{
1986    .debug-configuration = true ;
1987}
1988
1989# Miscellaneous constants.
1990.RM = [ common.rm-command ] ;
1991.nl = "
1992" ;
1993.ProgramFiles = [ path.make [ common.get-program-files-dir ] ] ;
1994.escaped-double-quote = "\"" ;
1995.TOUCH_FILE = [ common.file-touch-command ] ;
1996
1997# List of all registered configurations.
1998.versions = [ new configurations ] ;
1999
2000# Supported CPU architectures.
2001.cpu-arch-i386 =
2002    <architecture>/<address-model>
2003    <architecture>/<address-model>32
2004    <architecture>x86/<address-model>
2005    <architecture>x86/<address-model>32 ;
2006
2007.cpu-arch-amd64 =
2008    <architecture>/<address-model>64
2009    <architecture>x86/<address-model>64 ;
2010
2011.cpu-arch-ia64 =
2012    <architecture>ia64/<address-model>
2013    <architecture>ia64/<address-model>64 ;
2014
2015.cpu-arch-arm =
2016    <architecture>arm/<address-model>
2017    <architecture>arm/<address-model>32 ;
2018
2019.cpu-arch-arm64 =
2020    <architecture>arm/<address-model>
2021    <architecture>arm/<address-model>64 ;
2022
2023# Supported CPU types (only Itanium optimization options are supported from
2024# VC++ 2005 on). See
2025# http://msdn2.microsoft.com/en-us/library/h66s5s0e(vs.90).aspx for more
2026# detailed information.
2027.cpu-type-g5       = i586 pentium pentium-mmx ;
2028.cpu-type-g6       = i686 pentiumpro pentium2 pentium3 pentium3m pentium-m k6
2029                     k6-2 k6-3 winchip-c6 winchip2 c3 c3-2 c7 ;
2030.cpu-type-em64t    = prescott nocona core2 corei7 corei7-avx core-avx-i
2031                     conroe conroe-xe conroe-l allendale merom
2032                     merom-xe kentsfield kentsfield-xe penryn wolfdale
2033                     yorksfield nehalem sandy-bridge ivy-bridge haswell
2034                     broadwell skylake skylake-avx512 cannonlake icelake-client
2035                     icelake-server cascadelake cooperlake tigerlake ;
2036.cpu-type-amd64    = k8 opteron athlon64 athlon-fx k8-sse3 opteron-sse3
2037                     athlon64-sse3 amdfam10 barcelona bdver1 bdver2 bdver3
2038                     bdver4 btver1 btver2 znver1 znver2 ;
2039.cpu-type-g7       = pentium4 pentium4m athlon athlon-tbird athlon-4 athlon-xp
2040                     athlon-mp $(.cpu-type-em64t) $(.cpu-type-amd64) ;
2041.cpu-type-itanium  = itanium itanium1 merced ;
2042.cpu-type-itanium2 = itanium2 mckinley ;
2043.cpu-type-arm      = armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te armv6 armv6j iwmmxt ep9312
2044                     armv7 armv7s ;
2045
2046# Known toolset versions, in order of preference.
2047.known-versions = 14.2 14.1 14.0 12.0 11.0 10.0 10.0express 9.0 9.0express 8.0 8.0express 7.1
2048    7.1toolkit 7.0 6.0 ;
2049
2050# Version aliases.
2051.version-alias-6 = 6.0 ;
2052.version-alias-6.5 = 6.0 ;
2053.version-alias-7 = 7.0 ;
2054.version-alias-8 = 8.0 ;
2055.version-alias-9 = 9.0 ;
2056.version-alias-10 = 10.0 ;
2057.version-alias-11 = 11.0 ;
2058.version-alias-12 = 12.0 ;
2059.version-alias-14 = 14.0 ;
2060
2061# Names of registry keys containing the Visual C++ installation path (relative
2062# to "HKEY_LOCAL_MACHINE\SOFTWARE\\Microsoft").
2063.version-6.0-reg = "VisualStudio\\6.0\\Setup\\Microsoft Visual C++" ;
2064.version-7.0-reg = "VisualStudio\\7.0\\Setup\\VC" ;
2065.version-7.1-reg = "VisualStudio\\7.1\\Setup\\VC" ;
2066.version-8.0-reg = "VisualStudio\\8.0\\Setup\\VC" ;
2067.version-8.0express-reg = "VCExpress\\8.0\\Setup\\VC" ;
2068.version-9.0-reg = "VisualStudio\\9.0\\Setup\\VC" ;
2069.version-9.0express-reg = "VCExpress\\9.0\\Setup\\VC" ;
2070.version-10.0-reg = "VisualStudio\\10.0\\Setup\\VC" ;
2071.version-10.0express-reg = "VCExpress\\10.0\\Setup\\VC" ;
2072.version-11.0-reg = "VisualStudio\\11.0\\Setup\\VC" ;
2073.version-12.0-reg = "VisualStudio\\12.0\\Setup\\VC" ;
2074.version-14.0-reg = "VisualStudio\\14.0\\Setup\\VC" ;
2075
2076# Visual C++ Toolkit 2003 does not store its installation path in the registry.
2077# The environment variable 'VCToolkitInstallDir' and the default installation
2078# path will be checked instead.
2079.version-7.1toolkit-path    = "Microsoft Visual C++ Toolkit 2003/bin" ;
2080.version-7.1toolkit-env     = VCToolkitInstallDir ;
2081# Visual Studio 2017 doesn't use a registry at all. And the suggested methods
2082# of discovery involve having a compiled program. So as a fallback we search
2083# paths for VS2017 (aka msvc >= 14.1).
2084.version-14.1-path =
2085    "../../VC/Tools/MSVC/*/bin/Host*/*"
2086    "Microsoft Visual Studio/2017/*/VC/Tools/MSVC/*/bin/Host*/*"
2087    ;
2088.version-14.1-env = VS150COMNTOOLS ProgramFiles ProgramFiles(x86) ;
2089.version-14.2-path =
2090    "../../VC/Tools/MSVC/*/bin/Host*/*"
2091    "Microsoft Visual Studio/2019/*/VC/Tools/MSVC/*/bin/Host*/*"
2092    ;
2093.version-14.2-env = VS160COMNTOOLS ProgramFiles ProgramFiles(x86) ;
2094
2095# Auto-detect all the available msvc installations on the system.
2096auto-detect-toolset-versions ;
2097
2098
2099# And finally trigger the actual Boost Build toolset registration.
2100register-toolset ;
2101