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