1# Copyright 2022 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import("//build/config/clang/clang.gni") 6import("//build/config/compiler/compiler.gni") 7import("//build/config/rust.gni") 8import("//build/config/sanitizers/sanitizers.gni") 9import("//build/config/win/visual_studio_version.gni") 10import("//build/toolchain/cc_wrapper.gni") 11import("//build/toolchain/rbe.gni") 12import("//build/toolchain/toolchain.gni") 13import("//build/toolchain/win/win_toolchain_data.gni") 14 15assert(is_win, "Should only be running on Windows") 16 17# This tool will is used as a wrapper for various commands below. 18_tool_wrapper_path = 19 rebase_path("//build/toolchain/win/tool_wrapper.py", root_build_dir) 20 21if (host_os == "win") { 22 _exe = ".exe" 23} else { 24 _exe = "" 25} 26 27_clang_bin_path = rebase_path("$clang_base_path/bin", root_build_dir) 28 29# Makes a single MSVC toolchain. 30# 31# Parameters: 32# environment: File name of environment file. 33# 34# You would also define a toolchain_args variable with at least these set: 35# current_cpu: current_cpu to pass as a build arg 36# current_os: current_os to pass as a build arg 37template("msvc_toolchain") { 38 toolchain(target_name) { 39 # When invoking this toolchain not as the default one, these args will be 40 # passed to the build. They are ignored when this is the default toolchain. 41 assert(defined(invoker.toolchain_args)) 42 toolchain_args = { 43 forward_variables_from(invoker.toolchain_args, "*") 44 45 # This value needs to be passed through unchanged. 46 host_toolchain = host_toolchain 47 } 48 49 if (defined(toolchain_args.is_clang)) { 50 toolchain_is_clang = toolchain_args.is_clang 51 } else { 52 toolchain_is_clang = is_clang 53 } 54 55 # When the invoker has explicitly overridden use_remoteexec or cc_wrapper in 56 # the toolchain args, use those values, otherwise default to the global one. 57 # This works because the only reasonable override that toolchains might 58 # supply for these values are to force-disable them. 59 if (defined(toolchain_args.use_remoteexec)) { 60 toolchain_uses_remoteexec = toolchain_args.use_remoteexec 61 } else { 62 toolchain_uses_remoteexec = use_remoteexec 63 } 64 if (defined(toolchain_args.cc_wrapper)) { 65 toolchain_cc_wrapper = toolchain_args.cc_wrapper 66 } else { 67 toolchain_cc_wrapper = cc_wrapper 68 } 69 assert(!(toolchain_cc_wrapper != "" && toolchain_uses_remoteexec), 70 "re-client and cc_wrapper can't be used together.") 71 72 if (toolchain_uses_remoteexec) { 73 if (toolchain_is_clang) { 74 cl_prefix = "${rbe_bin_dir}/rewrapper -cfg=${rbe_cc_cfg_file}${rbe_bug_326584510_missing_inputs} -exec_root=${rbe_exec_root} -labels=type=compile,compiler=clang-cl,lang=cpp " 75 } else { 76 cl_prefix = "" 77 } 78 } else if (toolchain_cc_wrapper != "" && toolchain_is_clang) { 79 cl_prefix = toolchain_cc_wrapper + " " 80 } else { 81 cl_prefix = "" 82 } 83 84 cl = "${cl_prefix}${invoker.cl}" 85 if (host_os == "win") { 86 # Flip the slashes so that copy/paste of the command works. 87 cl = string_replace(cl, "/", "\\") 88 } 89 90 # Make these apply to all tools below. 91 lib_switch = "" 92 lib_dir_switch = "/LIBPATH:" 93 94 # Object files go in this directory. 95 object_subdir = "{{target_out_dir}}/{{label_name}}" 96 97 env = invoker.environment 98 99 if (use_lld) { 100 # lld-link includes a replacement for lib.exe that can produce thin 101 # archives and understands bitcode (for lto builds). 102 link = "${_clang_bin_path}/lld-link${_exe}" 103 cc_linkflags = "" 104 if (toolchain_has_rust) { 105 rust_linkflags = "" 106 } 107 if (host_os == "win") { 108 # Flip the slashes so that copy/paste of the commands works. 109 link = string_replace(link, "/", "\\") 110 } 111 lib = "$link /lib" 112 if (host_os != "win") { 113 # See comment adding --rsp-quoting to $cl above for more information. 114 cc_linkflags += " --rsp-quoting=posix" 115 if (toolchain_has_rust) { 116 rust_linkflags += " -Clink-arg=--rsp-quoting=posix" 117 } 118 } 119 } else { 120 lib = "lib.exe" 121 link = "link.exe" 122 cc_linkflags = "" 123 if (toolchain_has_rust) { 124 rust_linkflags = "" 125 } 126 } 127 128 # If possible, pass system includes as flags to the compiler. When that's 129 # not possible, load a full environment file (containing %INCLUDE% and 130 # %PATH%) -- e.g. 32-bit MSVS builds require %PATH% to be set and just 131 # passing in a list of include directories isn't enough. 132 if (defined(invoker.sys_include_flags)) { 133 env_wrapper = "" 134 sys_include_flags = 135 "${invoker.sys_include_flags} " # Note trailing space. 136 } else { 137 # clang-cl doesn't need this env hoop, so omit it there. 138 assert(!toolchain_is_clang) 139 env_wrapper = "ninja -t msvc -e $env -- " # Note trailing space. 140 sys_include_flags = "" 141 } 142 143 if (host_os != "win" || (use_lld && defined(invoker.sys_lib_flags))) { 144 linker_wrapper = "" 145 sys_lib_flags = "${invoker.sys_lib_flags}" 146 147 # TODO(thakis): Remove once crbug.com/1300005 is fixed 148 assert(toolchain_args.current_cpu == "x64" || 149 toolchain_args.current_cpu == "x86" || 150 toolchain_args.current_cpu == "arm" || 151 toolchain_args.current_cpu == "arm64", 152 "Only supports x64, x86, arm and arm64 CPUs") 153 if (toolchain_args.current_cpu == "x64") { 154 sys_lib_flags += " /MACHINE:X64" 155 } else if (toolchain_args.current_cpu == "x86") { 156 sys_lib_flags += " /MACHINE:X86" 157 } else if (toolchain_args.current_cpu == "arm") { 158 sys_lib_flags += " /MACHINE:ARM" 159 } else if (toolchain_args.current_cpu == "arm64") { 160 sys_lib_flags += " /MACHINE:ARM64" 161 } 162 163 sys_lib_flags += " " # Note trailing space. 164 } else { 165 # link.exe must be run under a wrapper to set up the environment 166 # (it needs %LIB% set to find libraries), and to work around its bugs. 167 # Note trailing space: 168 linker_wrapper = 169 "\"$python_path\" $_tool_wrapper_path link-wrapper $env False " 170 sys_lib_flags = "" 171 } 172 173 if (defined(toolchain_args.use_clang_coverage)) { 174 toolchain_use_clang_coverage = toolchain_args.use_clang_coverage 175 } else { 176 toolchain_use_clang_coverage = use_clang_coverage 177 } 178 179 if (toolchain_use_clang_coverage) { 180 assert(toolchain_is_clang, 181 "use_clang_coverage should only be used with Clang") 182 if (defined(toolchain_args.coverage_instrumentation_input_file)) { 183 toolchain_coverage_instrumentation_input_file = 184 toolchain_args.coverage_instrumentation_input_file 185 } else { 186 toolchain_coverage_instrumentation_input_file = 187 coverage_instrumentation_input_file 188 } 189 190 coverage_wrapper = 191 rebase_path("//build/toolchain/clang_code_coverage_wrapper.py", 192 root_build_dir) 193 coverage_wrapper = coverage_wrapper + " --target-os=" + target_os 194 if (toolchain_coverage_instrumentation_input_file != "") { 195 coverage_wrapper = 196 coverage_wrapper + " --files-to-instrument=" + 197 rebase_path(toolchain_coverage_instrumentation_input_file, 198 root_build_dir) 199 } 200 coverage_wrapper = "\"$python_path\" " + coverage_wrapper + " " 201 } else { 202 coverage_wrapper = "" 203 } 204 205 # Disabled with cc_wrapper because of 206 # https://github.com/mozilla/sccache/issues/1013 207 if (toolchain_is_clang && toolchain_cc_wrapper == "") { 208 # This flag omits system includes from /showIncludes output, to reduce 209 # the amount of data to parse and store in .ninja_deps. We do this on 210 # non-Windows too, and already make sure rebuilds after winsdk/libc++/ 211 # clang header updates happen via changing command line flags. 212 show_includes = "/showIncludes:user" 213 } else { 214 show_includes = "/showIncludes" 215 } 216 217 tool("cc") { 218 precompiled_header_type = "msvc" 219 pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" 220 221 # Label names may have spaces in them so the pdbname must be quoted. The 222 # source and output don't need to be quoted because GN knows they're a 223 # full file name and will quote automatically when necessary. 224 depsformat = "msvc" 225 description = "CC {{output}}" 226 outputs = [ "$object_subdir/{{source_name_part}}.obj" ] 227 228 # Note that the code coverage wrapper scripts assumes that {{source}} 229 # comes immediately after /c. 230 command = "$coverage_wrapper$env_wrapper$cl /c {{source}} /nologo $show_includes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} /Fo{{output}} /Fd\"$pdbname\"" 231 } 232 233 tool("cxx") { 234 precompiled_header_type = "msvc" 235 236 # The PDB name needs to be different between C and C++ compiled files. 237 pdbname = "{{target_out_dir}}/{{label_name}}_cc.pdb" 238 239 # See comment in CC tool about quoting. 240 depsformat = "msvc" 241 description = "CXX {{output}}" 242 outputs = [ "$object_subdir/{{source_name_part}}.obj" ] 243 244 # Note that the code coverage wrapper scripts assumes that {{source}} 245 # comes immediately after /c. 246 command = "$coverage_wrapper$env_wrapper$cl /c {{source}} /Fo{{output}} /nologo $show_includes $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} /Fd\"$pdbname\"" 247 } 248 249 tool("rc") { 250 command = "\"$python_path\" $_tool_wrapper_path rc-wrapper $env rc.exe /nologo $sys_include_flags{{defines}} {{include_dirs}} /fo{{output}} {{source}}" 251 depsformat = "msvc" 252 outputs = [ "$object_subdir/{{source_name_part}}.res" ] 253 description = "RC {{output}}" 254 } 255 256 tool("asm") { 257 is_msvc_assembler = true 258 259 if (toolchain_args.current_cpu == "arm64") { 260 if (toolchain_is_clang) { 261 ml = "${cl_prefix}${_clang_bin_path}/clang-cl${_exe} --target=aarch64-pc-windows" 262 if (host_os == "win") { 263 # Flip the slashes so that copy/paste of the command works. 264 ml = string_replace(ml, "/", "\\") 265 } 266 ml += " -c -o{{output}}" 267 is_msvc_assembler = false 268 } else { 269 # Only affects Arm builds with is_clang = false, implemented for 270 # building V8 for Windows on Arm systems with the MSVC toolchain. 271 ml = "armasm64.exe" 272 } 273 } else { 274 if (toolchain_is_clang && !disable_llvm_ml) { 275 prefix = rebase_path("$clang_base_path/bin", root_build_dir) 276 ml = "$prefix/llvm-ml${_exe}" 277 if (toolchain_args.current_cpu == "x64") { 278 ml += " -m64" 279 } else { 280 ml += " -m32" 281 } 282 } else { 283 if (toolchain_args.current_cpu == "x64") { 284 ml = "ml64.exe" 285 } else { 286 ml = "ml.exe" 287 } 288 } 289 } 290 291 if (is_msvc_assembler) { 292 ml += " /nologo /Fo{{output}}" 293 294 # Suppress final-stage linking on x64/x86 builds. (Armasm64 does not 295 # require /c because it doesn't support linking.) 296 if (toolchain_args.current_cpu != "arm64") { 297 ml += " /c" 298 } 299 if (use_lld && (!toolchain_is_clang || disable_llvm_ml)) { 300 # Wrap ml(64).exe with a script that makes its output deterministic. 301 # It's lld only because the script zaps obj Timestamp which 302 # link.exe /incremental looks at. 303 ml_py = rebase_path("//build/toolchain/win/ml.py", root_build_dir) 304 ml = "\"$python_path\" $ml_py $ml" 305 } 306 307 if (toolchain_args.current_cpu == "arm64") { 308 # armasm64.exe does not support definitions passed via the command 309 # line. (Fortunately, they're not needed for compiling the V8 310 # snapshot, which is the only time this assembler is required.) 311 command = "\"$python_path\" $_tool_wrapper_path asm-wrapper $env $ml {{include_dirs}} {{asmflags}} {{source}}" 312 } else { 313 command = "\"$python_path\" $_tool_wrapper_path asm-wrapper $env $ml {{defines}} {{include_dirs}} {{asmflags}} {{source}}" 314 } 315 } else { 316 command = "$ml {{defines}} {{include_dirs}} {{asmflags}} {{source}}" 317 } 318 319 description = "ASM {{output}}" 320 outputs = [ "$object_subdir/{{source_name_part}}.obj" ] 321 } 322 323 if (toolchain_has_rust) { 324 rust_sysroot_relative = rebase_path(rust_sysroot, root_build_dir) 325 rustc = "$rust_sysroot_relative/bin/rustc" 326 rustc_wrapper = 327 rebase_path("//build/rust/rustc_wrapper.py", root_build_dir) 328 rustc_windows_args = " -Clinker=$link$rust_linkflags $rustc_common_args" 329 330 tool("rust_staticlib") { 331 libname = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 332 rspfile = "$libname.rsp" 333 depfile = "$libname.d" 334 335 default_output_extension = ".lib" 336 output_prefix = "lib" 337 338 # Static libraries go in the target out directory by default so we can 339 # generate different targets with the same name and not have them 340 # collide. 341 default_output_dir = "{{target_out_dir}}" 342 description = "RUST(STATICLIB) {{output}}" 343 outputs = [ libname ] 344 345 rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}" 346 command = "\"$python_path\" \"$rustc_wrapper\" --target-windows --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_windows_args --emit=dep-info=$depfile,link -o $libname LDFLAGS RUSTENV {{rustenv}}" 347 rust_sysroot = rust_sysroot_relative 348 } 349 350 tool("rust_rlib") { 351 # We must always prefix with `lib` even if the library already starts 352 # with that prefix or else our stdlib is unable to find libc.rlib (or 353 # actually liblibc.rlib). 354 rlibname = 355 "{{output_dir}}/lib{{target_output_name}}{{output_extension}}" 356 rspfile = "$rlibname.rsp" 357 depfile = "$rlibname.d" 358 359 default_output_extension = ".rlib" 360 361 # This is prefixed unconditionally in `rlibname`. 362 # output_prefix = "lib" 363 364 # Static libraries go in the target out directory by default so we can 365 # generate different targets with the same name and not have them 366 # collide. 367 default_output_dir = "{{target_out_dir}}" 368 description = "RUST {{output}}" 369 outputs = [ rlibname ] 370 371 rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}" 372 command = "\"$python_path\" \"$rustc_wrapper\" --target-windows --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_windows_args --emit=dep-info=$depfile,link -o $rlibname {{rustdeps}} {{externs}} LDFLAGS RUSTENV {{rustenv}}" 373 rust_sysroot = rust_sysroot_relative 374 } 375 376 tool("rust_bin") { 377 exename = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 378 pdbname = "$exename.pdb" 379 rspfile = "$exename.rsp" 380 depfile = "$exename.d" 381 pool = "//build/toolchain:link_pool($default_toolchain)" 382 383 default_output_extension = ".exe" 384 default_output_dir = "{{root_out_dir}}" 385 description = "RUST(BIN) {{output}}" 386 outputs = [ 387 # The first entry here is used for dependency tracking. 388 exename, 389 pdbname, 390 ] 391 runtime_outputs = outputs 392 393 rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}" 394 dynamic_link_switch = "" 395 command = "\"$python_path\" \"$rustc_wrapper\" --target-windows --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_windows_args --emit=dep-info=$depfile,link -o $exename LDFLAGS {{ldflags}} $sys_lib_flags /PDB:$pdbname RUSTENV {{rustenv}}" 396 rust_sysroot = rust_sysroot_relative 397 } 398 399 tool("rust_cdylib") { 400 # E.g. "foo.dll": 401 dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 402 libname = "$dllname.lib" # e.g. foo.dll.lib 403 pdbname = "$dllname.pdb" 404 rspfile = "$dllname.rsp" 405 depfile = "$dllname.d" 406 pool = "//build/toolchain:link_pool($default_toolchain)" 407 408 default_output_extension = ".dll" 409 default_output_dir = "{{root_out_dir}}" 410 description = "RUST(CDYLIB) {{output}}" 411 outputs = [ 412 # The first entry here is used for dependency tracking. Dylibs are 413 # linked into other targets and that linking must be done through 414 # the .lib file, not the .dll file. So the .lib file is the primary 415 # output here. 416 libname, 417 dllname, 418 pdbname, 419 ] 420 runtime_outputs = [ 421 dllname, 422 pdbname, 423 ] 424 425 rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}" 426 dynamic_link_switch = "" 427 command = "\"$python_path\" \"$rustc_wrapper\" --target-windows --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_windows_args --emit=dep-info=$depfile,link -o $dllname LDFLAGS {{ldflags}} $sys_lib_flags /PDB:$pdbname /IMPLIB:$libname RUSTENV {{rustenv}}" 428 rust_sysroot = rust_sysroot_relative 429 430 # Since the above commands only updates the .lib file when it changes, 431 # ask Ninja to check if the timestamp actually changed to know if 432 # downstream dependencies should be recompiled. 433 restat = true 434 } 435 436 tool("rust_macro") { 437 # E.g. "foo.dll": 438 dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 439 pdbname = "$dllname.pdb" 440 rspfile = "$dllname.rsp" 441 depfile = "$dllname.d" 442 pool = "//build/toolchain:link_pool($default_toolchain)" 443 444 default_output_extension = ".dll" 445 default_output_dir = "{{root_out_dir}}" 446 description = "RUST(MACRO) {{output}}" 447 outputs = [ 448 # The first entry here is used for dependency tracking. Proc macros 449 # are consumed as dlls directly, loaded a runtime, so the dll is the 450 # primary output here. If we make a .lib file the primary output, we 451 # end up trying to load the .lib file as a procmacro which fails. 452 # 453 # Since depending on a macro target for linking would fail (it would 454 # try to link primary .dll target) we omit the .lib here entirely. 455 dllname, 456 pdbname, 457 ] 458 runtime_outputs = outputs 459 460 rspfile_content = "{{rustdeps}} {{externs}} SOURCES {{sources}}" 461 dynamic_link_switch = "" 462 command = "\"$python_path\" \"$rustc_wrapper\" --target-windows --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- $rustc_windows_args --emit=dep-info=$depfile,link -o $dllname LDFLAGS {{ldflags}} $sys_lib_flags /PDB:$pdbname RUSTENV {{rustenv}}" 463 rust_sysroot = rust_sysroot_relative 464 465 # Since the above commands only updates the .lib file when it changes, 466 # ask Ninja to check if the timestamp actually changed to know if 467 # downstream dependencies should be recompiled. 468 restat = true 469 } 470 } 471 472 tool("alink") { 473 rspfile = "{{output}}.rsp" 474 command = "$linker_wrapper$lib \"/OUT:{{output}}\" /nologo {{arflags}} \"@$rspfile\"" 475 description = "LIB {{output}}" 476 outputs = [ 477 # Ignore {{output_extension}} and always use .lib, there's no reason to 478 # allow targets to override this extension on Windows. 479 "{{output_dir}}/{{target_output_name}}.lib", 480 ] 481 default_output_extension = ".lib" 482 default_output_dir = "{{target_out_dir}}" 483 484 # The use of inputs_newline is to work around a fixed per-line buffer 485 # size in the linker. 486 rspfile_content = "{{inputs_newline}}" 487 } 488 489 tool("solink") { 490 # E.g. "foo.dll": 491 dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 492 libname = "${dllname}.lib" # e.g. foo.dll.lib 493 pdbname = "${dllname}.pdb" 494 rspfile = "${dllname}.rsp" 495 pool = "//build/toolchain:link_pool($default_toolchain)" 496 497 command = "$linker_wrapper$link$cc_linkflags \"/OUT:$dllname\" /nologo ${sys_lib_flags} \"/IMPLIB:$libname\" /DLL \"/PDB:$pdbname\" \"@$rspfile\"" 498 499 default_output_extension = ".dll" 500 default_output_dir = "{{root_out_dir}}" 501 description = "LINK(DLL) {{output}}" 502 outputs = [ 503 dllname, 504 libname, 505 pdbname, 506 ] 507 link_output = libname 508 depend_output = libname 509 runtime_outputs = [ 510 dllname, 511 pdbname, 512 ] 513 514 # Since the above commands only updates the .lib file when it changes, 515 # ask Ninja to check if the timestamp actually changed to know if 516 # downstream dependencies should be recompiled. 517 restat = true 518 519 # The use of inputs_newline is to work around a fixed per-line buffer 520 # size in the linker. 521 rspfile_content = 522 "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}} {{rlibs}}" 523 } 524 525 tool("solink_module") { 526 # E.g. "foo.dll": 527 dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 528 pdbname = "${dllname}.pdb" 529 rspfile = "${dllname}.rsp" 530 pool = "//build/toolchain:link_pool($default_toolchain)" 531 532 command = "$linker_wrapper$link$cc_linkflags \"/OUT:$dllname\" /nologo ${sys_lib_flags} /DLL \"/PDB:$pdbname\" \"@$rspfile\"" 533 534 default_output_extension = ".dll" 535 default_output_dir = "{{root_out_dir}}" 536 description = "LINK_MODULE(DLL) {{output}}" 537 outputs = [ 538 dllname, 539 pdbname, 540 ] 541 runtime_outputs = outputs 542 543 # The use of inputs_newline is to work around a fixed per-line buffer 544 # size in the linker. 545 rspfile_content = 546 "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}} {{rlibs}}" 547 } 548 549 tool("link") { 550 exename = "{{output_dir}}/{{target_output_name}}{{output_extension}}" 551 pdbname = "$exename.pdb" 552 rspfile = "$exename.rsp" 553 pool = "//build/toolchain:link_pool($default_toolchain)" 554 555 command = "$linker_wrapper$link$cc_linkflags \"/OUT:$exename\" /nologo ${sys_lib_flags} \"/PDB:$pdbname\" \"@$rspfile\"" 556 557 default_output_extension = ".exe" 558 default_output_dir = "{{root_out_dir}}" 559 description = "LINK {{output}}" 560 outputs = [ 561 exename, 562 pdbname, 563 ] 564 runtime_outputs = outputs 565 566 # The use of inputs_newline is to work around a fixed per-line buffer 567 # size in the linker. 568 rspfile_content = 569 "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}} {{rlibs}}" 570 } 571 572 # These two are really entirely generic, but have to be repeated in 573 # each toolchain because GN doesn't allow a template to be used here. 574 # See //build/toolchain/toolchain.gni for details. 575 tool("stamp") { 576 command = stamp_command 577 description = stamp_description 578 pool = "//build/toolchain:action_pool($default_toolchain)" 579 } 580 tool("copy") { 581 command = copy_command 582 description = copy_description 583 pool = "//build/toolchain:action_pool($default_toolchain)" 584 } 585 586 tool("action") { 587 pool = "//build/toolchain:action_pool($default_toolchain)" 588 } 589 } 590} 591 592template("msvc_rust_host_build_tools_toolchain") { 593 assert(defined(invoker.toolchain_args)) 594 if (enable_rust) { 595 msvc_toolchain("${target_name}_for_rust_host_build_tools") { 596 forward_variables_from(invoker, 597 "*", 598 [ 599 "toolchain_args", 600 "visibility", 601 "testonly", 602 ]) 603 toolchain_args = { 604 # Populate toolchain args from the invoker. 605 forward_variables_from(invoker.toolchain_args, "*") 606 toolchain_for_rust_host_build_tools = true 607 608 # The host build tools are static release builds to make the Chromium 609 # build faster. They do not need PGO etc, so no official builds. 610 is_debug = false 611 is_component_build = false 612 is_official_build = false 613 use_clang_coverage = false 614 use_sanitizer_coverage = false 615 generate_linker_map = false 616 use_thin_lto = false 617 } 618 } 619 } else { 620 not_needed(invoker, "*") 621 not_needed([ "target_name" ]) 622 } 623} 624 625template("win_toolchains") { 626 # On Windows, cross-compile for x86 changes the `host_toolchain` 627 # into x86 too so as to avoid compiling things twice (see 628 # //build/config/BUILDCONFIG.gn). But the prebuilt stdlib does not 629 # exist for Windows x86 and it's exceedingly difficult to get it 630 # built from a single build_rust.py invocation. So we just don't follow 631 # along in the `msvc_rust_host_build_tools_toolchain` toolchains, and 632 # always use the host cpu type (which will be x64 in that case). Things 633 # built with these toolchains are never built for the target_cpu anyhow, 634 # so the optimization there does not benefit them. 635 # 636 # Thus, in msvc_rust_host_build_tools_toolchain: 637 # * Use `rust_host_toolchain_arch` instead of `toolchain_arch`. 638 # * Use `rust_host_win_toolchain_data` instead of `win_toolchain_data`. 639 640 assert(defined(invoker.toolchain_arch)) 641 toolchain_arch = invoker.toolchain_arch 642 rust_host_toolchain_arch = host_cpu 643 644 # The toolchain data for `msvc_toolchain()`. 645 if (toolchain_arch == "x86") { 646 win_toolchain_data = win_toolchain_data_x86 647 } else if (toolchain_arch == "x64") { 648 win_toolchain_data = win_toolchain_data_x64 649 } else if (toolchain_arch == "arm64") { 650 win_toolchain_data = win_toolchain_data_arm64 651 } else { 652 error("Unsupported toolchain_arch, add it to win_toolchain_data.gni") 653 } 654 655 # The toolchain data for `msvc_rust_host_build_tools_toolchain()`. 656 if (rust_host_toolchain_arch == "x86") { 657 rust_host_win_toolchain_data = win_toolchain_data_x86 658 } else if (rust_host_toolchain_arch == "x64") { 659 rust_host_win_toolchain_data = win_toolchain_data_x64 660 } else if (rust_host_toolchain_arch == "arm64") { 661 rust_host_win_toolchain_data = win_toolchain_data_arm64 662 } else { 663 error( 664 "Unsupported rust_host_toolchain_arch, add it to win_toolchain_data.gni") 665 } 666 667 # The toolchain using MSVC only makes sense when not doing cross builds. 668 # Chromium exclusively uses the win_clang_ toolchain below, but V8 and 669 # WebRTC still use this MSVC toolchain in some cases. 670 if (host_os == "win") { 671 if (defined(invoker.cl_toolchain_prefix)) { 672 cl_toolchain_prefix = invoker.cl_toolchain_prefix 673 } else { 674 cl_toolchain_prefix = "" 675 } 676 msvc_toolchain(cl_toolchain_prefix + target_name) { 677 environment = "environment." + toolchain_arch 678 cl = "\"${win_toolchain_data.vc_bin_dir}/cl.exe\"" 679 680 toolchain_args = { 681 if (defined(invoker.toolchain_args)) { 682 forward_variables_from(invoker.toolchain_args, "*") 683 } 684 is_clang = false 685 use_clang_coverage = false 686 current_os = "win" 687 current_cpu = toolchain_arch 688 } 689 } 690 msvc_rust_host_build_tools_toolchain(cl_toolchain_prefix + target_name) { 691 environment = "environment." + rust_host_toolchain_arch 692 cl = "\"${rust_host_win_toolchain_data.vc_bin_dir}/cl.exe\"" 693 694 toolchain_args = { 695 if (defined(invoker.toolchain_args)) { 696 forward_variables_from(invoker.toolchain_args, "*") 697 } 698 is_clang = false 699 use_clang_coverage = false 700 current_os = "win" 701 current_cpu = rust_host_toolchain_arch 702 } 703 } 704 } 705 706 if (defined(invoker.clang_toolchain_prefix)) { 707 clang_toolchain_prefix = invoker.clang_toolchain_prefix 708 } else { 709 clang_toolchain_prefix = "win_clang_" 710 } 711 712 _clang_lib_dir = 713 rebase_path("$clang_base_path/lib/clang/$clang_version/lib/windows", 714 root_build_dir) 715 if (host_os == "win") { 716 # And to match the other -libpath flags. 717 _clang_lib_dir = string_replace(_clang_lib_dir, "/", "\\") 718 } 719 720 msvc_toolchain(clang_toolchain_prefix + target_name) { 721 environment = "environment." + toolchain_arch 722 cl = "${_clang_bin_path}/clang-cl${_exe}" 723 724 sys_include_flags = "${win_toolchain_data.include_flags_imsvc}" 725 if (use_lld) { 726 sys_lib_flags = "-libpath:$_clang_lib_dir " + 727 "${win_toolchain_data.libpath_lldlink_flags}" 728 } 729 730 toolchain_args = { 731 if (defined(invoker.toolchain_args)) { 732 forward_variables_from(invoker.toolchain_args, "*") 733 } 734 is_clang = true 735 current_os = "win" 736 current_cpu = toolchain_arch 737 } 738 } 739 msvc_rust_host_build_tools_toolchain(clang_toolchain_prefix + target_name) { 740 environment = "environment." + rust_host_toolchain_arch 741 cl = "${_clang_bin_path}/clang-cl${_exe}" 742 743 sys_include_flags = "${rust_host_win_toolchain_data.include_flags_imsvc}" 744 if (use_lld) { 745 sys_lib_flags = "-libpath:$_clang_lib_dir " + 746 "${rust_host_win_toolchain_data.libpath_lldlink_flags}" 747 } 748 749 toolchain_args = { 750 if (defined(invoker.toolchain_args)) { 751 forward_variables_from(invoker.toolchain_args, "*") 752 } 753 is_clang = true 754 current_os = "win" 755 current_cpu = rust_host_toolchain_arch 756 } 757 } 758} 759