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