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 # Use this for {{output_extension}} expansions unless a target manually 419 # overrides it (in which case {{output_extension}} will be what the target 420 # specifies). 421 default_output_extension = default_shlib_extension 422 423 default_output_dir = "{{root_out_dir}}" 424 425 output_prefix = "lib" 426 427 # Since the above commands only updates the .TOC file when it changes, ask 428 # Ninja to check if the timestamp actually changed to know if downstream 429 # dependencies should be recompiled. 430 restat = true 431 432 # Tell GN about the output files. It will link to the sofile 433 outputs = [ sofile ] 434 if (sofile != unstripped_sofile) { 435 outputs += [ unstripped_sofile ] 436 if (defined(invoker.use_unstripped_as_runtime_outputs) && 437 invoker.use_unstripped_as_runtime_outputs) { 438 runtime_outputs = [ unstripped_sofile ] 439 } 440 } 441 if (defined(map_file)) { 442 outputs += [ map_file ] 443 } 444 445 if (is_mingw_link) { 446 outputs += [ libfile ] 447 link_output = libfile 448 depend_output = libfile 449 } else { 450 link_output = sofile 451 depend_output = sofile 452 } 453 } 454 455 tool("solink_module") { 456 soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so". 457 sofile = "{{output_dir}}/$soname" 458 rspfile = sofile + ".rsp" 459 pool = "//build/toolchain:link_pool($default_toolchain)" 460 461 if (defined(invoker.strip)) { 462 unstripped_sofile = "{{root_out_dir}}/lib.unstripped/$sofile" 463 } else { 464 unstripped_sofile = sofile 465 } 466 467 command = "$ld -shared {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" -Wl,-soname=\"$soname\" @\"$rspfile\"" 468 469 if (defined(invoker.strip)) { 470 strip_command = "${invoker.strip} -o \"$sofile\" \"$unstripped_sofile\"" 471 command += " && " + strip_command 472 } 473 rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix" 474 475 description = "SOLINK_MODULE $sofile" 476 477 # Use this for {{output_extension}} expansions unless a target manually 478 # overrides it (in which case {{output_extension}} will be what the target 479 # specifies). 480 if (defined(invoker.loadable_module_extension)) { 481 default_output_extension = invoker.loadable_module_extension 482 } else { 483 default_output_extension = default_shlib_extension 484 } 485 486 default_output_dir = "{{root_out_dir}}" 487 488 output_prefix = "lib" 489 490 outputs = [ sofile ] 491 if (sofile != unstripped_sofile) { 492 outputs += [ unstripped_sofile ] 493 if (defined(invoker.use_unstripped_as_runtime_outputs) && 494 invoker.use_unstripped_as_runtime_outputs) { 495 runtime_outputs = [ unstripped_sofile ] 496 } 497 } 498 } 499 500 tool("link") { 501 exename = "{{target_output_name}}{{output_extension}}" 502 outfile = "{{output_dir}}/$exename" 503 rspfile = "$outfile.rsp" 504 unstripped_outfile = outfile 505 pool = "//build/toolchain:link_pool($default_toolchain)" 506 507 # Use this for {{output_extension}} expansions unless a target manually 508 # overrides it (in which case {{output_extension}} will be what the target 509 # specifies). 510 default_output_extension = default_executable_extension 511 512 default_output_dir = "{{root_out_dir}}" 513 514 if (defined(invoker.strip)) { 515 unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$outfile" 516 } 517 518 # Generate a map file to be used for binary size analysis. 519 # Map file adds ~10% to the link time on a z620. 520 map_switch = "" 521 if (enable_linker_map && is_official_build) { 522 map_file = "$unstripped_outfile.map.gz" 523 map_switch = " --map-file \"$map_file\"" 524 } 525 526 start_group_flag = "" 527 end_group_flag = "" 528 if (current_os != "aix") { 529 # the "--start-group .. --end-group" feature isn't available on the aix ld. 530 start_group_flag = "-Wl,--start-group" 531 end_group_flag = "-Wl,--end-group " 532 } 533 _clang_rt_dso_full_path = "" 534 if (is_asan && invoker_toolchain_args.current_os == "ohos") { 535 if (use_hwasan) { 536 _clang_rt_dso_full_path = rebase_path( 537 "$clang_base_path/lib/clang/$clang_version/lib/aarch64-linux-ohos/libclang_rt.hwasan.so", 538 root_build_dir) 539 } else if (invoker_toolchain_args.current_cpu == "arm64") { 540 _clang_rt_dso_full_path = rebase_path( 541 "$clang_base_path/lib/clang/$clang_version/lib/aarch64-linux-ohos/libclang_rt.asan.so", 542 root_build_dir) 543 } else if (invoker_toolchain_args.current_cpu == "riscv64") { 544 _clang_rt_dso_full_path = rebase_path( 545 "$clang_base_path/lib/clang/$clang_version/lib/riscv64-linux-ohos/libclang_rt.asan.so", 546 root_build_dir) 547 } else { 548 _clang_rt_dso_full_path = rebase_path( 549 "$clang_base_path/lib/clang/$clang_version/lib/arm-linux-ohos/libclang_rt.asan.so", 550 root_build_dir) 551 } 552 } 553 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" 554 555 strip_switch = "" 556 557 if (defined(invoker.strip)) { 558 strip_switch = " --strip=\"${invoker.strip}\" --unstripped-file=\"$unstripped_outfile\"" 559 } 560 if (is_asan && invoker_toolchain_args.current_os == "ohos") { 561 strip_switch = 562 "$strip_switch --clang_rt_dso_path=\"$_clang_rt_dso_full_path\"" 563 } 564 565 link_wrapper = 566 rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir) 567 _clang_base_dir = rebase_path(toolchains_dir) 568 command = "$python_path \"$link_wrapper\" --output=\"$outfile\"$strip_switch$map_switch --clang-base-dir=\"$_clang_base_dir\" " 569 if (full_mini_debug && !is_debug) { 570 command = "$command --mini-debug" 571 } 572 command = "$command -- $link_command" 573 description = "LINK $outfile" 574 rspfile_content = "{{inputs}}" 575 outputs = [ outfile ] 576 if (outfile != unstripped_outfile) { 577 outputs += [ unstripped_outfile ] 578 if (defined(invoker.use_unstripped_as_runtime_outputs) && 579 invoker.use_unstripped_as_runtime_outputs) { 580 runtime_outputs = [ unstripped_outfile ] 581 } 582 } 583 if (defined(invoker.link_outputs)) { 584 outputs += invoker.link_outputs 585 } 586 if (defined(map_file)) { 587 outputs += [ map_file ] 588 } 589 } 590 591 # These two are really entirely generic, but have to be repeated in 592 # each toolchain because GN doesn't allow a template to be used here. 593 # See //build/toolchain/toolchain.gni for details. 594 tool("stamp") { 595 command = stamp_command 596 description = stamp_description 597 } 598 tool("copy") { 599 command = copy_command 600 description = copy_description 601 } 602 603 if (!is_arkui_x) { 604 cc_command_args = "" 605 if (defined(invoker.cc_command_args)) { 606 cc_command_args = invoker.cc_command_args 607 } 608 609 rust_sysroot_relative_to_out = rebase_path(rust_sysroot, root_out_dir) 610 rustc_wrapper = 611 rebase_path("//build/toolchain/rustc_wrapper.py", root_build_dir) 612 _clang_base_dir = rebase_path(toolchains_dir) 613 tool("rust_staticlib") { 614 staticlibname = 615 "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.a". 616 outfile = "{{target_out_dir}}/$staticlibname" 617 depfile = "$outfile.d" 618 rspfile = "$outfile.rsp" 619 rspfile_content = "{{rustdeps}} {{externs}}" 620 621 pool = "//build/toolchain:link_pool($default_toolchain)" 622 623 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}} -C prefer-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}}" 624 625 description = "RUST staticlib $outfile" 626 rust_sysroot = rust_sysroot_relative_to_out 627 outputs = [ outfile ] 628 default_output_extension = ".a" 629 output_prefix = "lib" 630 } 631 632 tool("rust_rlib") { 633 rlibname = 634 "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.rlib". 635 outfile = "{{output_dir}}/$rlibname" 636 depfile = "$outfile.d" 637 rspfile = "$outfile.rsp" 638 rspfile_content = "{{rustdeps}} {{externs}}" 639 640 # Don't add rspfile in rust_rlib tool. 641 pool = "//build/toolchain:link_pool($default_toolchain)" 642 643 command = "$python_path \"$rustc_wrapper\" --clang-base-dir=$_clang_base_dir --clippy-driver=$clippy_driver --rustc=$rustc --depfile=$depfile -- --crate-name {{crate_name}} -C prefer-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}}" 644 description = "RUST rlib $outfile" 645 rust_sysroot = rust_sysroot_relative_to_out 646 outputs = [ outfile ] 647 default_output_extension = default_rlib_extension 648 output_prefix = "lib" 649 } 650 651 tool("rust_cdylib") { 652 cdylibname = 653 "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.z.so". 654 outfile = "{{output_dir}}/$cdylibname" 655 depfile = "$outfile.d" 656 rspfile = "$outfile.rsp" 657 rspfile_content = "{{rustdeps}} {{externs}}" 658 659 unstripped_outfile = "{{root_out_dir}}/lib.unstripped/$outfile" 660 661 pool = "//build/toolchain:link_pool($default_toolchain)" 662 663 strip_level = "none" # rustc supports none, debuginfo and symbols 664 # three strip degree. 665 strip_switch = " -C strip=$strip_level" 666 667 minidebug_switch = "" 668 if (full_mini_debug && !is_debug) { 669 minidebug_switch = " --mini-debug" 670 } 671 672 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}} -C prefer-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,-soname=\"$cdylibname\" -o $unstripped_outfile LDFLAGS {{ldflags}} RUSTENV {{rustenv}}" 673 674 description = "RUST cdylib $outfile" 675 rust_sysroot = rust_sysroot_relative_to_out 676 outputs = [ unstripped_outfile ] 677 outputs += [ outfile ] 678 default_output_extension = default_shlib_extension 679 output_prefix = "lib" 680 } 681 682 tool("rust_bin") { 683 exename = "{{target_output_name}}{{output_extension}}" 684 outfile = "{{output_dir}}/$exename" 685 depfile = "$outfile.d" 686 rspfile = "$outfile.rsp" 687 rspfile_content = "{{rustdeps}} {{externs}}" 688 689 unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$outfile" 690 691 pool = "//build/toolchain:link_pool($default_toolchain)" 692 693 strip_level = "none" # rustc supports none, debuginfo and symbols 694 # three strip degree. 695 strip_switch = " -C strip=$strip_level" 696 minidebug_switch = "" 697 if (full_mini_debug && !is_debug) { 698 minidebug_switch = " --mini-debug" 699 } 700 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}}" 701 702 description = "RUST bin $outfile" 703 rust_sysroot = rust_sysroot_relative_to_out 704 outputs = [ unstripped_outfile ] 705 outputs += [ outfile ] 706 default_output_extension = default_executable_extension 707 } 708 709 tool("rust_dylib") { 710 dylibname = 711 "{{target_output_name}}{{output_extension}}" # e.g. 712 # "libfoo.dylib.so". 713 outfile = "{{output_dir}}/$dylibname" 714 depfile = "$outfile.d" 715 rspfile = "$outfile.rsp" 716 rspfile_content = "{{rustdeps}} {{externs}}" 717 718 unstripped_outfile = "{{root_out_dir}}/lib.unstripped/$outfile" 719 720 pool = "//build/toolchain:link_pool($default_toolchain)" 721 722 strip_level = "none" # rustc supports none, debuginfo and symbols 723 # three strip degree. 724 strip_switch = " -C strip=$strip_level" 725 minidebug_switch = "" 726 if (full_mini_debug && !is_debug) { 727 minidebug_switch = " --mini-debug" 728 } 729 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}} -C prefer-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}}" 730 731 description = "RUST dylib $outfile" 732 rust_sysroot = rust_sysroot_relative_to_out 733 outputs = [ unstripped_outfile ] 734 outputs += [ outfile ] 735 default_output_extension = default_dylib_extension 736 output_prefix = "lib" 737 } 738 739 tool("rust_macro") { 740 dylibname = 741 "{{target_output_name}}{{output_extension}}" # e.g. 742 # "libfoo.dylib.so". 743 outfile = "{{output_dir}}/$dylibname" 744 depfile = "$outfile.d" 745 rspfile = "$outfile.rsp" 746 rspfile_content = "{{rustdeps}} {{externs}}" 747 748 unstripped_outfile = "{{root_out_dir}}/lib.unstripped/$outfile" 749 750 pool = "//build/toolchain:link_pool($default_toolchain)" 751 752 strip_level = "none" # rustc supports none, debuginfo and symbols 753 # three strip degree. 754 strip_switch = " -C strip=$strip_level" 755 minidebug_switch = "" 756 if (full_mini_debug && !is_debug) { 757 minidebug_switch = " --mini-debug" 758 } 759 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}} -C prefer-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}}" 760 761 description = "RUST proc-macro $outfile" 762 rust_sysroot = rust_sysroot_relative_to_out 763 outputs = [ unstripped_outfile ] 764 outputs += [ outfile ] 765 default_output_extension = default_dylib_extension 766 output_prefix = "lib" 767 } 768 } 769 770 tool("action") { 771 pool = "//build/toolchain:action_pool($default_toolchain)" 772 } 773 774 forward_variables_from(invoker, [ "deps" ]) 775 } 776} 777 778# This is a shorthand for gcc_toolchain instances based on the Chromium-built 779# version of Clang. Only the toolchain_cpu and toolchain_os variables need to 780# be specified by the invoker, and optionally toolprefix if it's a 781# cross-compile case. Note that for a cross-compile case this toolchain 782# requires a config to pass the appropriate -target option, or else it will 783# actually just be doing a native compile. The invoker can optionally override 784# use_gold too. 785template("clang_toolchain") { 786 if (defined(invoker.toolprefix)) { 787 toolprefix = invoker.toolprefix 788 } else { 789 toolprefix = "" 790 } 791 792 gcc_toolchain(target_name) { 793 prefix = rebase_path("$clang_base_path/bin", root_build_dir) 794 cc = "$prefix/clang" 795 cxx = "$prefix/clang++" 796 ld = cxx 797 readelf = "${toolprefix}readelf" 798 ar = "${prefix}/llvm-ar" 799 nm = "${toolprefix}nm" 800 801 forward_variables_from(invoker, 802 [ 803 "strip", 804 "is_clang_analysis_supported", 805 "enable_linker_map", 806 "use_unstripped_as_runtime_outputs", 807 "rust_abi_target", 808 ]) 809 810 toolchain_args = { 811 if (defined(invoker.toolchain_args)) { 812 forward_variables_from(invoker.toolchain_args, "*") 813 } 814 is_clang = true 815 } 816 817 if (defined(invoker.shlib_extension) && invoker.shlib_extension != "") { 818 shlib_extension = invoker.shlib_extension 819 } 820 if (defined(rust_abi_target)) { 821 if (rust_abi_target == "x86_64-unknown-linux-gnu") { 822 clang_lib_path = rebase_path("$clang_base_path/lib", root_build_dir) 823 cc_command_args = "--target=${rust_abi_target} -Clinker=$clang -lstdc++ -lclang -L${clang_lib_path} -Clink-arg=-fuse-ld=lld -Clink-arg=-v" 824 } 825 } 826 } 827} 828