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