1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2013 The Chromium Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7import("//build/config/clang/clang.gni") 8import("//build/config/compiler/compiler.gni") 9import("//build/config/sanitizers/sanitizers.gni") 10import("//build/config/v8_target_cpu.gni") 11import("//build/toolchain/cc_wrapper.gni") 12import("//build/toolchain/clang_static_analyzer.gni") 13import("//build/toolchain/toolchain.gni") 14 15if (!is_arkui_x) { 16 import("//build/rust/rustc_toolchain.gni") 17} 18 19if (is_nacl) { 20 # To keep NaCl variables out of builds that don't include NaCl, all 21 # variables defined in nacl/config.gni referenced here should be protected by 22 # is_nacl conditions. 23 import("//build/config/nacl/config.gni") 24} 25 26declare_args() { 27 # Enables allowlist generation for IDR_ grit defines seen by the compiler. 28 # Currently works only on ohos and enabled by default for release builds. 29 # Requires debug info, so disabled for symbol_level=0 & strip_debug_info=true. 30 enable_resource_allowlist_generation = 31 is_ohos && !is_debug && 32 # Always enable for official builds, but enable for release builds by 33 # default only when other args allow. 34 (is_official_build || 35 (!strip_debug_info && symbol_level > 0 && !is_component_build)) 36} 37 38declare_args() { 39 share_ccache = "" 40} 41 42# When the arg is set via args.gn, it applies to all toolchains. In order to not 43# hit the assert in grit_rule.gni, explicitly disable for host toolchains. 44if (is_linux && target_os == "ohos") { 45 enable_resource_allowlist_generation = false 46} 47 48# Path to the Clang static analysis wrapper script. 49# REVIEWERS: can you suggest a better location for this? 50# GN is really picky about dead stores of variables except at the global scope. 51analyzer_wrapper = 52 rebase_path("//build/toolchain/clang_static_analyzer_wrapper.py", 53 root_build_dir) + " --mode=clang" 54 55# This template defines a toolchain for something that works like gcc 56# (including clang). 57# 58# It requires the following variables specifying the executables to run: 59# - ar 60# - cc 61# - cxx 62# - ld 63# 64# Optional parameters that control the tools: 65# 66# - extra_cflags 67# Extra flags to be appended when compiling C files (but not C++ files). 68# - extra_cppflags 69# Extra flags to be appended when compiling both C and C++ files. "CPP" 70# stands for "C PreProcessor" in this context, although it can be 71# used for non-preprocessor flags as well. Not to be confused with 72# "CXX" (which follows). 73# - extra_cxxflags 74# Extra flags to be appended when compiling C++ files (but not C files). 75# - extra_asmflags 76# Extra flags to be appended when compiling assembly. 77# - extra_ldflags 78# Extra flags to be appended when linking 79# 80# - libs_section_prefix 81# - libs_section_postfix 82# The contents of these strings, if specified, will be placed around 83# the libs section of the linker line. It allows one to inject libraries 84# at the beginning and end for all targets in a toolchain. 85# - solink_libs_section_prefix 86# - solink_libs_section_postfix 87# Same as libs_section_{pre,post}fix except used for solink instead of link. 88# - link_outputs 89# The content of this array, if specified, will be added to the list of 90# outputs from the link command. This can be useful in conjunction with 91# the post_link parameter. 92# - use_unstripped_as_runtime_outputs 93# When |strip| is set, mark unstripped executables as runtime deps rather 94# than stripped ones. 95# - post_link 96# The content of this string, if specified, will be run as a separate 97# command following the the link command. 98# - deps 99# Just forwarded to the toolchain definition. 100# - executable_extension 101# If this string is specified it will be used for the file extension 102# for an executable, rather than using no extension; targets will 103# still be able to override the extension using the output_extension 104# variable. 105# - rebuild_define 106# The contents of this string, if specified, will be passed as a #define 107# to the toolchain. It can be used to force recompiles whenever a 108# toolchain is updated. 109# - shlib_extension 110# If this string is specified it will be used for the file extension 111# for a shared library, rather than default value specified in 112# toolchain.gni 113# - strip 114# Location of the strip executable. When specified, strip will be run on 115# all shared libraries and executables as they are built. The pre-stripped 116# artifacts will be put in lib.unstripped/ and exe.unstripped/. 117template("gcc_toolchain") { 118 toolchain(target_name) { 119 assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ar\" value") 120 assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value") 121 assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value") 122 assert(defined(invoker.ld), "gcc_toolchain() must specify a \"ld\" value") 123 124 # This define changes when the toolchain changes, forcing a rebuild. 125 # Nothing should ever use this define. 126 if (defined(invoker.rebuild_define)) { 127 rebuild_string = "-D" + invoker.rebuild_define + " " 128 } else { 129 rebuild_string = "" 130 } 131 132 # GN's syntax can't handle more than one scope dereference at once, like 133 # "invoker.toolchain_args.foo", so make a temporary to hold the toolchain 134 # args so we can do "invoker_toolchain_args.foo". 135 assert(defined(invoker.toolchain_args), 136 "Toolchains must specify toolchain_args") 137 invoker_toolchain_args = invoker.toolchain_args 138 assert(defined(invoker_toolchain_args.current_cpu), 139 "toolchain_args must specify a current_cpu") 140 assert(defined(invoker_toolchain_args.current_os), 141 "toolchain_args must specify a current_os") 142 143 # When invoking this toolchain not as the default one, these args will be 144 # passed to the build. They are ignored when this is the default toolchain. 145 toolchain_args = { 146 # Populate toolchain args from the invoker. 147 forward_variables_from(invoker_toolchain_args, "*") 148 149 # The host toolchain value computed by the default toolchain's setup 150 # needs to be passed through unchanged to all secondary toolchains to 151 # ensure that it's always the same, regardless of the values that may be 152 # set on those toolchains. 153 host_toolchain = host_toolchain 154 155 if (!defined(invoker_toolchain_args.v8_current_cpu)) { 156 v8_current_cpu = invoker_toolchain_args.current_cpu 157 } 158 } 159 160 if (is_clang && use_clang_static_analyzer && 161 (!defined(invoker.is_clang_analysis_supported) || 162 invoker.is_clang_analysis_supported)) { 163 compiler_prefix = "${analyzer_wrapper} " 164 asm = invoker.cc 165 } else { 166 if (defined(toolchain_args.cc_wrapper)) { 167 toolchain_cc_wrapper = toolchain_args.cc_wrapper 168 } else { 169 toolchain_cc_wrapper = cc_wrapper 170 } 171 if (share_ccache != "") { 172 compiler_prefix = "CCACHE_DIR=" + share_ccache + 173 " CCACHE_NOHASHDIR=1 ${toolchain_cc_wrapper} " 174 } else { 175 compiler_prefix = "${toolchain_cc_wrapper} " 176 } 177 } 178 179 cc = compiler_prefix + invoker.cc 180 cxx = compiler_prefix + invoker.cxx 181 ar = invoker.ar 182 ld = invoker.ld 183 if (!defined(asm)) { 184 asm = cc 185 } 186 if (defined(invoker.readelf)) { 187 readelf = invoker.readelf 188 } else { 189 readelf = "readelf" 190 } 191 if (defined(invoker.nm)) { 192 nm = invoker.nm 193 } else { 194 nm = "nm" 195 } 196 197 if (defined(invoker.shlib_extension)) { 198 default_shlib_extension = invoker.shlib_extension 199 } else { 200 default_shlib_extension = shlib_extension 201 } 202 203 if (defined(invoker.executable_extension)) { 204 default_executable_extension = invoker.executable_extension 205 } else { 206 default_executable_extension = "" 207 } 208 209 if (!is_arkui_x) { 210 if (defined(invoker.dylib_extension)) { 211 default_dylib_extension = invoker.dylib_extension 212 } else { 213 default_dylib_extension = dylib_extension 214 } 215 216 if (defined(invoker.rlib_extension)) { 217 default_rlib_extension = invoker.rlib_extension 218 } else { 219 default_rlib_extension = rlib_extension 220 } 221 } 222 223 # Bring these into our scope for string interpolation with default values. 224 if (defined(invoker.libs_section_prefix)) { 225 libs_section_prefix = invoker.libs_section_prefix 226 } else { 227 libs_section_prefix = "" 228 } 229 230 if (defined(invoker.libs_section_postfix)) { 231 libs_section_postfix = invoker.libs_section_postfix 232 } else { 233 libs_section_postfix = "" 234 } 235 236 if (defined(invoker.solink_libs_section_prefix)) { 237 solink_libs_section_prefix = invoker.solink_libs_section_prefix 238 } else { 239 solink_libs_section_prefix = "" 240 } 241 242 if (defined(invoker.solink_libs_section_postfix)) { 243 solink_libs_section_postfix = invoker.solink_libs_section_postfix 244 } else { 245 solink_libs_section_postfix = "" 246 } 247 248 if (defined(invoker.extra_cflags) && invoker.extra_cflags != "") { 249 extra_cflags = " " + invoker.extra_cflags 250 } else { 251 extra_cflags = "" 252 } 253 254 if (defined(invoker.extra_cppflags) && invoker.extra_cppflags != "") { 255 extra_cppflags = " " + invoker.extra_cppflags 256 } else { 257 extra_cppflags = "" 258 } 259 260 if (defined(invoker.extra_cxxflags) && invoker.extra_cxxflags != "") { 261 extra_cxxflags = " " + invoker.extra_cxxflags 262 } else { 263 extra_cxxflags = "" 264 } 265 266 if (defined(invoker.extra_asmflags) && invoker.extra_asmflags != "") { 267 extra_asmflags = " " + invoker.extra_asmflags 268 } else { 269 extra_asmflags = "" 270 } 271 272 if (defined(invoker.extra_ldflags) && invoker.extra_ldflags != "") { 273 extra_ldflags = " " + invoker.extra_ldflags 274 } else { 275 extra_ldflags = "" 276 } 277 278 enable_linker_map = defined(invoker.enable_linker_map) && 279 invoker.enable_linker_map && generate_linker_map 280 281 # These library switches can apply to all tools below. 282 lib_switch = "-l" 283 lib_dir_switch = "-L" 284 285 # Object files go in this directory. 286 object_subdir = "{{source_out_dir}}/{{label_name}}" 287 288 tool("cc") { 289 depfile = "{{output}}.d" 290 command = "$cc -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}${extra_cppflags}${extra_cflags} -c {{source}} -o {{output}}" 291 depsformat = "gcc" 292 description = "CC {{output}}" 293 outputs = [ "$object_subdir/{{source_name_part}}.o" ] 294 } 295 296 tool("cxx") { 297 depfile = "{{output}}.d" 298 command = "$cxx -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}${extra_cppflags}${extra_cxxflags} -c {{source}} -o {{output}}" 299 depsformat = "gcc" 300 description = "CXX {{output}}" 301 outputs = [ "$object_subdir/{{source_name_part}}.o" ] 302 } 303 304 tool("asm") { 305 # For GCC we can just use the C compiler to compile assembly. 306 depfile = "{{output}}.d" 307 command = "$asm -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{asmflags}}${extra_asmflags} -c {{source}} -o {{output}}" 308 depsformat = "gcc" 309 description = "ASM {{output}}" 310 outputs = [ "$object_subdir/{{source_name_part}}.o" ] 311 } 312 313 tool("alink") { 314 if (current_os == "aix") { 315 # AIX does not support either -D (deterministic output) or response 316 # files. 317 command = "$ar -X64 {{arflags}} -r -c -s {{output}} {{inputs}}" 318 } else { 319 rspfile = "{{output}}.rsp" 320 rspfile_content = "{{inputs}}" 321 command = "\"$ar\" {{arflags}} -r -c -s -D {{output}} @\"$rspfile\"" 322 } 323 324 # Remove the output file first so that ar doesn't try to modify the 325 # existing file. 326 if (host_os == "win") { 327 tool_wrapper_path = 328 rebase_path("//build/toolchain/win/tool_wrapper.py", root_build_dir) 329 command = "cmd /c $python_path $tool_wrapper_path delete-file {{output}} && $command" 330 } else { 331 command = "rm -f {{output}} && $command" 332 } 333 334 # Almost all targets build with //build/config/compiler:thin_archive which 335 # adds -T to arflags. 336 description = "AR {{output}}" 337 outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ] 338 339 # Shared libraries go in the target out directory by default so we can 340 # generate different targets with the same name and not have them collide. 341 default_output_dir = "{{target_out_dir}}" 342 default_output_extension = ".a" 343 output_prefix = "lib" 344 } 345 346 tool("solink") { 347 soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so". 348 sofile = "{{output_dir}}/$soname" # Possibly including toolchain dir. 349 rspfile = sofile + ".rsp" 350 pool = "//build/toolchain:link_pool($default_toolchain)" 351 352 is_mingw_link = false 353 if (invoker_toolchain_args.current_os == "mingw") { 354 is_mingw_link = true 355 libname = "{{target_output_name}}.lib" 356 libfile = "{{output_dir}}/$libname" 357 } 358 359 if (defined(invoker.strip)) { 360 unstripped_sofile = "{{root_out_dir}}/lib.unstripped/$sofile" 361 } else { 362 unstripped_sofile = sofile 363 } 364 365 link_command = "$ld -shared {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" @\"$rspfile\"" 366 if (!is_mingw_link) { 367 link_command = "$link_command -Wl,-soname=\"$soname\"" 368 } else { 369 link_command = "$link_command -Wl,--out-implib,{{root_out_dir}}/lib.unstripped/$libfile" 370 } 371 372 # Generate a map file to be used for binary size analysis. 373 # Map file adds ~10% to the link time on a z620. 374 map_switch = "" 375 if (enable_linker_map && is_official_build) { 376 map_file = "$unstripped_sofile.map.gz" 377 map_switch = " --map-file \"$map_file\"" 378 } 379 380 assert(defined(readelf), "to solink you must have a readelf") 381 assert(defined(nm), "to solink you must have an nm") 382 strip_switch = "" 383 if (defined(invoker.strip)) { 384 strip_switch = "--strip=${invoker.strip} " 385 if (current_cpu == "arm" && is_standard_system) { 386 strip_debug_whitelist = 387 rebase_path("//build/toolchain/strip_debug_whitelist.txt", 388 root_build_dir) 389 strip_switch += "--strip-debug-whitelist=${strip_debug_whitelist} " 390 } 391 } 392 adlt_switch = "" 393 if (enable_adlt && allowed_lib_list != "") { 394 adlt_switch = "--target-name={{label_name}}" + 395 " --target-out-dir={{target_out_dir}}" + 396 " --allowed-lib-list=" + rebase_path(allowed_lib_list) 397 } 398 399 # This needs a Python script to avoid using a complex shell command 400 # requiring sh control structures, pipelines, and POSIX utilities. 401 # The host might not have a POSIX shell and utilities (e.g. Windows). 402 solink_wrapper = 403 rebase_path("//build/toolchain/gcc_solink_wrapper.py", root_build_dir) 404 _clang_base_dir = rebase_path(toolchains_dir) 405 command = "$python_path \"$solink_wrapper\" --readelf=\"$readelf\" --nm=\"$nm\" $strip_switch $adlt_switch --sofile=\"$unstripped_sofile\" $map_switch --output=\"$sofile\" --clang-base-dir=\"$_clang_base_dir\"" 406 if (is_mingw_link) { 407 command = "$command --libfile=\"$libfile\"" 408 } 409 if (full_mini_debug && !is_debug) { 410 command = "$command --mini-debug" 411 } 412 command = "$command -- $link_command" 413 414 rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix" 415 416 description = "SOLINK $sofile" 417 418 # Declares toolchain solink to be compiled as whole-archive by default. 419 toolchain_whole_archive = true 420 421 # Use this for {{output_extension}} expansions unless a target manually 422 # overrides it (in which case {{output_extension}} will be what the target 423 # specifies). 424 default_output_extension = default_shlib_extension 425 426 default_output_dir = "{{root_out_dir}}" 427 428 output_prefix = "lib" 429 430 # Since the above commands only updates the .TOC file when it changes, ask 431 # Ninja to check if the timestamp actually changed to know if downstream 432 # dependencies should be recompiled. 433 restat = true 434 435 # Tell GN about the output files. It will link to the sofile 436 outputs = [ sofile ] 437 if (sofile != unstripped_sofile) { 438 outputs += [ unstripped_sofile ] 439 if (defined(invoker.use_unstripped_as_runtime_outputs) && 440 invoker.use_unstripped_as_runtime_outputs) { 441 runtime_outputs = [ unstripped_sofile ] 442 } 443 } 444 if (defined(map_file)) { 445 outputs += [ map_file ] 446 } 447 448 if (is_mingw_link) { 449 outputs += [ libfile ] 450 link_output = libfile 451 depend_output = libfile 452 } else { 453 link_output = sofile 454 depend_output = sofile 455 } 456 } 457 458 tool("solink_module") { 459 soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so". 460 sofile = "{{output_dir}}/$soname" 461 rspfile = sofile + ".rsp" 462 pool = "//build/toolchain:link_pool($default_toolchain)" 463 464 if (defined(invoker.strip)) { 465 unstripped_sofile = "{{root_out_dir}}/lib.unstripped/$sofile" 466 } else { 467 unstripped_sofile = sofile 468 } 469 470 command = "$ld -shared {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" -Wl,-soname=\"$soname\" @\"$rspfile\"" 471 472 if (defined(invoker.strip)) { 473 strip_command = "${invoker.strip} -o \"$sofile\" \"$unstripped_sofile\"" 474 command += " && " + strip_command 475 } 476 rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix" 477 478 description = "SOLINK_MODULE $sofile" 479 480 # Use this for {{output_extension}} expansions unless a target manually 481 # overrides it (in which case {{output_extension}} will be what the target 482 # specifies). 483 if (defined(invoker.loadable_module_extension)) { 484 default_output_extension = invoker.loadable_module_extension 485 } else { 486 default_output_extension = default_shlib_extension 487 } 488 489 default_output_dir = "{{root_out_dir}}" 490 491 output_prefix = "lib" 492 493 outputs = [ sofile ] 494 if (sofile != unstripped_sofile) { 495 outputs += [ unstripped_sofile ] 496 if (defined(invoker.use_unstripped_as_runtime_outputs) && 497 invoker.use_unstripped_as_runtime_outputs) { 498 runtime_outputs = [ unstripped_sofile ] 499 } 500 } 501 } 502 503 tool("link") { 504 exename = "{{target_output_name}}{{output_extension}}" 505 outfile = "{{output_dir}}/$exename" 506 rspfile = "$outfile.rsp" 507 unstripped_outfile = outfile 508 pool = "//build/toolchain:link_pool($default_toolchain)" 509 510 # Use this for {{output_extension}} expansions unless a target manually 511 # overrides it (in which case {{output_extension}} will be what the target 512 # specifies). 513 default_output_extension = default_executable_extension 514 515 default_output_dir = "{{root_out_dir}}" 516 517 if (defined(invoker.strip)) { 518 unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$outfile" 519 } 520 521 # Generate a map file to be used for binary size analysis. 522 # Map file adds ~10% to the link time on a z620. 523 map_switch = "" 524 if (enable_linker_map && is_official_build) { 525 map_file = "$unstripped_outfile.map.gz" 526 map_switch = " --map-file \"$map_file\"" 527 } 528 529 start_group_flag = "" 530 end_group_flag = "" 531 if (current_os != "aix") { 532 # the "--start-group .. --end-group" feature isn't available on the aix ld. 533 start_group_flag = "-Wl,--start-group" 534 end_group_flag = "-Wl,--end-group " 535 } 536 _clang_rt_dso_full_path = "" 537 if (is_asan && invoker_toolchain_args.current_os == "ohos") { 538 if (use_hwasan) { 539 _clang_rt_dso_full_path = rebase_path( 540 "$clang_base_path/lib/clang/$clang_version/lib/aarch64-linux-ohos/libclang_rt.hwasan.so", 541 root_build_dir) 542 } else if (invoker_toolchain_args.current_cpu == "arm64") { 543 _clang_rt_dso_full_path = rebase_path( 544 "$clang_base_path/lib/clang/$clang_version/lib/aarch64-linux-ohos/libclang_rt.asan.so", 545 root_build_dir) 546 } else if (invoker_toolchain_args.current_cpu == "riscv64") { 547 _clang_rt_dso_full_path = rebase_path( 548 "$clang_base_path/lib/clang/$clang_version/lib/riscv64-linux-ohos/libclang_rt.asan.so", 549 root_build_dir) 550 } else { 551 _clang_rt_dso_full_path = rebase_path( 552 "$clang_base_path/lib/clang/$clang_version/lib/arm-linux-ohos/libclang_rt.asan.so", 553 root_build_dir) 554 } 555 } 556 link_command = "$ld {{ldflags}}${extra_ldflags} -o \"$unstripped_outfile\" $libs_section_prefix $start_group_flag $_clang_rt_dso_full_path @\"$rspfile\" {{solibs}} {{libs}} $end_group_flag $libs_section_postfix" 557 558 strip_switch = "" 559 560 if (defined(invoker.strip)) { 561 strip_switch = " --strip=\"${invoker.strip}\" --unstripped-file=\"$unstripped_outfile\"" 562 } 563 if (is_asan && invoker_toolchain_args.current_os == "ohos") { 564 strip_switch = 565 "$strip_switch --clang_rt_dso_path=\"$_clang_rt_dso_full_path\"" 566 } 567 568 link_wrapper = 569 rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir) 570 _clang_base_dir = rebase_path(toolchains_dir) 571 command = "$python_path \"$link_wrapper\" --output=\"$outfile\"$strip_switch$map_switch --clang-base-dir=\"$_clang_base_dir\" " 572 if (full_mini_debug && !is_debug) { 573 command = "$command --mini-debug" 574 } 575 command = "$command -- $link_command" 576 description = "LINK $outfile" 577 rspfile_content = "{{inputs}}" 578 outputs = [ outfile ] 579 if (outfile != unstripped_outfile) { 580 outputs += [ unstripped_outfile ] 581 if (defined(invoker.use_unstripped_as_runtime_outputs) && 582 invoker.use_unstripped_as_runtime_outputs) { 583 runtime_outputs = [ unstripped_outfile ] 584 } 585 } 586 if (defined(invoker.link_outputs)) { 587 outputs += invoker.link_outputs 588 } 589 if (defined(map_file)) { 590 outputs += [ map_file ] 591 } 592 } 593 594 # These two are really entirely generic, but have to be repeated in 595 # each toolchain because GN doesn't allow a template to be used here. 596 # See //build/toolchain/toolchain.gni for details. 597 tool("stamp") { 598 command = stamp_command 599 description = stamp_description 600 } 601 tool("copy") { 602 command = copy_command 603 description = copy_description 604 } 605 606 if (!is_arkui_x) { 607 cc_command_args = "" 608 if (defined(invoker.cc_command_args)) { 609 cc_command_args = invoker.cc_command_args 610 } 611 if (invoker_toolchain_args.current_os == "mingw") { 612 rust_dynamic = "" 613 } else { 614 rust_dynamic = "-C prefer-dynamic" 615 } 616 minidebug_switch = "" 617 if (full_mini_debug && !is_debug) { 618 minidebug_switch = " --mini-debug" 619 } 620 rust_sysroot_relative_to_out = rebase_path(rust_sysroot, root_out_dir) 621 rustc_wrapper = 622 rebase_path("//build/toolchain/rustc_wrapper.py", root_build_dir) 623 _clang_base_dir = rebase_path(toolchains_dir) 624 tool("rust_staticlib") { 625 staticlibname = 626 "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.a". 627 outfile = "{{target_out_dir}}/$staticlibname" 628 depfile = "$outfile.d" 629 rspfile = "$outfile.rsp" 630 rspfile_content = "{{rustdeps}} {{externs}}" 631 632 pool = "//build/toolchain:link_pool($default_toolchain)" 633 634 command = "$python_path \"$rustc_wrapper\" --clang-base-dir=$_clang_base_dir --clippy-driver=$clippy_driver --rustc=$rustc --depfile=$depfile --rsp=$rspfile -- --crate-name {{crate_name}} $rust_dynamic {{source}} --crate-type {{crate_type}} $cc_command_args --emit=dep-info=$depfile,link -Z dep-info-omit-d-target -Z unstable-options {{rustflags}} -o $outfile LDFLAGS RUSTENV {{rustenv}}" 635 636 description = "RUST staticlib $outfile" 637 rust_sysroot = rust_sysroot_relative_to_out 638 outputs = [ outfile ] 639 default_output_extension = ".a" 640 output_prefix = "lib" 641 } 642 643 tool("rust_rlib") { 644 rlibname = 645 "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.rlib". 646 outfile = "{{output_dir}}/$rlibname" 647 depfile = "$outfile.d" 648 rspfile = "$outfile.rsp" 649 rspfile_content = "{{rustdeps}} {{externs}}" 650 651 # Don't add rspfile in rust_rlib tool. 652 pool = "//build/toolchain:link_pool($default_toolchain)" 653 654 command = "$python_path \"$rustc_wrapper\" --clang-base-dir=$_clang_base_dir --clippy-driver=$clippy_driver --rustc=$rustc --depfile=$depfile -- --crate-name {{crate_name}} $rust_dynamic {{source}} --crate-type {{crate_type}} $cc_command_args {{rustdeps}} {{externs}} --emit=dep-info=$depfile,link -Z dep-info-omit-d-target -Z unstable-options {{rustflags}} -o $outfile LDFLAGS RUSTENV {{rustenv}}" 655 description = "RUST rlib $outfile" 656 rust_sysroot = rust_sysroot_relative_to_out 657 outputs = [ outfile ] 658 default_output_extension = default_rlib_extension 659 output_prefix = "lib" 660 } 661 if (invoker_toolchain_args.current_os == "mingw") { 662 cdylib_link_option = "--out-implib" 663 } else { 664 cdylib_link_option = "-soname" 665 } 666 tool("rust_cdylib") { 667 cdylibname = 668 "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.z.so". 669 outfile = "{{output_dir}}/$cdylibname" 670 depfile = "$outfile.d" 671 rspfile = "$outfile.rsp" 672 rspfile_content = "{{rustdeps}} {{externs}}" 673 674 unstripped_outfile = "{{root_out_dir}}/lib.unstripped/$outfile" 675 676 pool = "//build/toolchain:link_pool($default_toolchain)" 677 678 strip_level = "none" # rustc supports none, debuginfo and symbols 679 # three strip degree. 680 strip_switch = " -C strip=$strip_level" 681 682 minidebug_switch = "" 683 if (full_mini_debug && !is_debug) { 684 minidebug_switch = " --mini-debug" 685 } 686 687 command = "$python_path \"$rustc_wrapper\" --clang-base-dir=$_clang_base_dir --clippy-driver=$clippy_driver --rustc=$rustc --depfile=$depfile --rsp=$rspfile --output=$outfile --unstripped-file=$unstripped_outfile --strip=$llvm_strip $minidebug_switch -- --crate-name {{crate_name}} $rust_dynamic $strip_switch {{source}} --crate-type {{crate_type}} $cc_command_args --emit=dep-info=$depfile,link -Z dep-info-omit-d-target -Z unstable-options {{rustflags}} -Clink-arg=-Wl,$cdylib_link_option=\"$cdylibname\" -o $unstripped_outfile LDFLAGS {{ldflags}} RUSTENV {{rustenv}}" 688 689 description = "RUST cdylib $outfile" 690 rust_sysroot = rust_sysroot_relative_to_out 691 outputs = [ unstripped_outfile ] 692 outputs += [ outfile ] 693 default_output_extension = default_shlib_extension 694 output_prefix = "lib" 695 } 696 697 tool("rust_bin") { 698 exename = "{{target_output_name}}{{output_extension}}" 699 outfile = "{{output_dir}}/$exename" 700 depfile = "$outfile.d" 701 rspfile = "$outfile.rsp" 702 rspfile_content = "{{rustdeps}} {{externs}}" 703 704 unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$outfile" 705 706 pool = "//build/toolchain:link_pool($default_toolchain)" 707 708 strip_level = "none" # rustc supports none, debuginfo and symbols 709 # three strip degree. 710 strip_switch = " -C strip=$strip_level" 711 minidebug_switch = "" 712 if (full_mini_debug && !is_debug) { 713 minidebug_switch = " --mini-debug" 714 } 715 command = "$python_path \"$rustc_wrapper\" --clang-base-dir=$_clang_base_dir --clippy-driver=$clippy_driver --rustc=$rustc --depfile=$depfile --rsp=$rspfile --output=$outfile --unstripped-file=$unstripped_outfile --strip=$llvm_strip $minidebug_switch -- --crate-name {{crate_name}} $strip_switch {{source}} --crate-type {{crate_type}} $cc_command_args --emit=dep-info=$depfile,link -Z dep-info-omit-d-target -Z unstable-options {{rustflags}} -o $unstripped_outfile LDFLAGS RUSTENV {{rustenv}}" 716 717 description = "RUST bin $outfile" 718 rust_sysroot = rust_sysroot_relative_to_out 719 outputs = [ unstripped_outfile ] 720 outputs += [ outfile ] 721 default_output_extension = default_executable_extension 722 } 723 724 tool("rust_dylib") { 725 dylibname = 726 "{{target_output_name}}{{output_extension}}" # e.g. 727 # "libfoo.dylib.so". 728 outfile = "{{output_dir}}/$dylibname" 729 depfile = "$outfile.d" 730 rspfile = "$outfile.rsp" 731 rspfile_content = "{{rustdeps}} {{externs}}" 732 733 unstripped_outfile = "{{root_out_dir}}/lib.unstripped/$outfile" 734 735 pool = "//build/toolchain:link_pool($default_toolchain)" 736 737 strip_level = "none" # rustc supports none, debuginfo and symbols 738 # three strip degree. 739 strip_switch = " -C strip=$strip_level" 740 minidebug_switch = "" 741 if (full_mini_debug && !is_debug) { 742 minidebug_switch = " --mini-debug" 743 } 744 command = "$python_path \"$rustc_wrapper\" --clang-base-dir=$_clang_base_dir --clippy-driver=$clippy_driver --rustc=$rustc --depfile=$depfile --rsp=$rspfile --output=$outfile --unstripped-file=$unstripped_outfile --strip=$llvm_strip $minidebug_switch -- --crate-name {{crate_name}} $rust_dynamic $strip_switch {{source}} --crate-type {{crate_type}} $cc_command_args --emit=dep-info=$depfile,link -Z dep-info-omit-d-target -Z unstable-options {{rustflags}} -o $unstripped_outfile LDFLAGS {{ldflags}} RUSTENV {{rustenv}}" 745 746 description = "RUST dylib $outfile" 747 rust_sysroot = rust_sysroot_relative_to_out 748 outputs = [ unstripped_outfile ] 749 outputs += [ outfile ] 750 default_output_extension = default_dylib_extension 751 output_prefix = "lib" 752 } 753 754 tool("rust_macro") { 755 dylibname = 756 "{{target_output_name}}{{output_extension}}" # e.g. 757 # "libfoo.dylib.so". 758 outfile = "{{output_dir}}/$dylibname" 759 depfile = "$outfile.d" 760 rspfile = "$outfile.rsp" 761 rspfile_content = "{{rustdeps}} {{externs}}" 762 763 unstripped_outfile = "{{root_out_dir}}/lib.unstripped/$outfile" 764 765 pool = "//build/toolchain:link_pool($default_toolchain)" 766 767 strip_level = "none" # rustc supports none, debuginfo and symbols 768 # three strip degree. 769 strip_switch = " -C strip=$strip_level" 770 minidebug_switch = "" 771 if (full_mini_debug && !is_debug) { 772 minidebug_switch = " --mini-debug" 773 } 774 command = "$python_path \"$rustc_wrapper\" --clang-base-dir=$_clang_base_dir --clippy-driver=$clippy_driver --rustc=$rustc --depfile=$depfile --rsp=$rspfile --output=$outfile --unstripped-file=$unstripped_outfile --strip=$llvm_strip $minidebug_switch -- --crate-name {{crate_name}} $rust_dynamic $strip_switch {{source}} --crate-type {{crate_type}} $cc_command_args --emit=dep-info=$depfile,link -Z dep-info-omit-d-target -Z unstable-options {{rustflags}} -o $unstripped_outfile LDFLAGS {{ldflags}} RUSTENV {{rustenv}}" 775 776 description = "RUST proc-macro $outfile" 777 rust_sysroot = rust_sysroot_relative_to_out 778 outputs = [ unstripped_outfile ] 779 outputs += [ outfile ] 780 default_output_extension = default_dylib_extension 781 output_prefix = "lib" 782 } 783 } 784 785 tool("action") { 786 pool = "//build/toolchain:action_pool($default_toolchain)" 787 } 788 789 forward_variables_from(invoker, [ "deps" ]) 790 } 791} 792 793# This is a shorthand for gcc_toolchain instances based on the Chromium-built 794# version of Clang. Only the toolchain_cpu and toolchain_os variables need to 795# be specified by the invoker, and optionally toolprefix if it's a 796# cross-compile case. Note that for a cross-compile case this toolchain 797# requires a config to pass the appropriate -target option, or else it will 798# actually just be doing a native compile. The invoker can optionally override 799# use_gold too. 800template("clang_toolchain") { 801 if (defined(invoker.toolprefix)) { 802 toolprefix = invoker.toolprefix 803 } else { 804 toolprefix = "" 805 } 806 807 gcc_toolchain(target_name) { 808 prefix = rebase_path("$clang_base_path/bin", root_build_dir) 809 cc = "$prefix/clang" 810 cxx = "$prefix/clang++" 811 ld = cxx 812 readelf = "${toolprefix}readelf" 813 ar = "${prefix}/llvm-ar" 814 nm = "${toolprefix}nm" 815 816 forward_variables_from(invoker, 817 [ 818 "strip", 819 "is_clang_analysis_supported", 820 "enable_linker_map", 821 "use_unstripped_as_runtime_outputs", 822 "rust_abi_target", 823 ]) 824 825 toolchain_args = { 826 if (defined(invoker.toolchain_args)) { 827 forward_variables_from(invoker.toolchain_args, "*") 828 } 829 is_clang = true 830 } 831 832 if (defined(invoker.shlib_extension) && invoker.shlib_extension != "") { 833 shlib_extension = invoker.shlib_extension 834 } 835 if (defined(rust_abi_target)) { 836 if (rust_abi_target == "x86_64-unknown-linux-gnu") { 837 clang_lib_path = rebase_path("$clang_base_path/lib", root_build_dir) 838 cc_command_args = "--target=${rust_abi_target} -Clinker=$clang -lstdc++ -lclang -L${clang_lib_path} -Clink-arg=-fuse-ld=lld -Clink-arg=-v" 839 } 840 } 841 } 842} 843