| # Copyright 2021 The Chromium Project. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("//build/config/chrome_build.gni") |
| import("//build/config/compiler/compiler.gni") |
| import("//build/config/sanitizers/sanitizers.gni") |
| import("//build/toolchain/toolchain.gni") |
| |
| if (is_android) { |
| import("//build/config/android/config.gni") |
| } |
| |
| if (is_ios) { |
| # For `target_environment` and `target_platform`. |
| import("//build/config/apple/mobile_config.gni") |
| } |
| |
| declare_args() { |
| # Rust is available in the Chromium build but 3p repos that use //build may |
| # not use Rust and thus won't want to depend on having the Rust toolchain |
| # present, so this defaults to off in those cases. |
| # |
| # Chromium-based projects that are built for for architectures Chrome does not |
| # support may need to disable this as well, though they may need to replace |
| # code with C/C++ to get a functional product. |
| # |
| # Based on the above: |
| # |
| # * `enable_rust` may be consulted under `//build` and `//testing` directories |
| # (which may be used outside of Chromium build) |
| # * `enable_rust` should *not* be consulted in other Chromium directories |
| # (including `//base`, `//net`, etc.) |
| enable_rust = build_with_chromium |
| |
| # The CXX tool is in //third_party/rust which is not shared with downstream |
| # projects yet. So they need to copy the required dependencies and GN files |
| # into their project to enable CXX there. |
| # |
| # We do not support disabling this flag in Chromium code. |
| enable_rust_cxx = build_with_chromium |
| |
| # The chromium prelude crate provides the `chromium::import!` macro which |
| # is needed to depend on first-party rust libraries. Third-party libraries |
| # are specified with cargo_crate and do not get imported through this macro. |
| # |
| # The macro requires //third_party/rust for syn, quote, and proc_macro2. |
| # Downstream projects that want to use //build for the rust GN templates but |
| # don't want to enable the chromium prelude can disable it here, and should |
| # specify a globally unique `crate_name` in their rust library GN rules |
| # instead. Note that using a `crate_name` is strongly discouraged inside |
| # Chromium, and is also discouraged for downstream projects when possible. |
| # |
| # We do not support disabling this flag in Chromium code. |
| enable_chromium_prelude = build_with_chromium |
| |
| # Chromium provides a Rust toolchain in //third_party/rust-toolchain. |
| # |
| # To use a custom toolchain instead, specify an absolute path to the root of |
| # a Rust sysroot, which will have a 'bin' directory and others. Commonly |
| # <home dir>/.rustup/toolchains/nightly-<something>-<something> |
| rust_sysroot_absolute = "" |
| |
| # Directory under which to find `bin/bindgen` (a `bin` directory containing |
| # the bindgen exectuable). |
| rust_bindgen_root = "//third_party/rust-toolchain" |
| |
| # If you're using a Rust toolchain as specified by rust_sysroot_absolute, |
| # set this to the output of `rustc -V`. Changing this string will cause all |
| # Rust targets to be rebuilt, which allows you to update your toolchain and |
| # not break incremental builds. |
| rustc_version = "" |
| |
| # If you're using a Rust toolchain as specified by rust_sysroot_absolute, |
| # you can specify whether it supports nacl here. |
| rust_toolchain_supports_nacl = false |
| |
| # Whether artifacts produced by the Rust compiler can participate in ThinLTO. |
| # |
| # One important consideration is whether the linker uses the same LLVM |
| # version as `rustc` (i.e. if it can understand the LLVM-IR from the |
| # compilation artifacts produced by `rustc`). In LaCrOS and ash builds this |
| # may not be true - see b/299483903. |
| # |
| # TODO(crbug.com/40281834): Re-enable ThinLTO for Rust on LaCrOS |
| # TODO(b/300937673): Re-enable ThinLTO for Rust on ash-chrome |
| toolchain_supports_rust_thin_lto = !is_chromeos |
| |
| # Any extra std rlibs in your Rust toolchain, relative to the standard |
| # Rust toolchain. Typically used with 'rust_sysroot_absolute' |
| added_rust_stdlib_libs = [] |
| |
| # Any removed std rlibs in your Rust toolchain, relative to the standard |
| # Rust toolchain. Typically used with 'rust_sysroot_absolute' |
| removed_rust_stdlib_libs = [] |
| |
| # Non-rlib libs provided in the toolchain sysroot. Usually this is empty, but |
| # e.g. the Android Rust Toolchain provides a libunwind.a that rustc expects. |
| extra_sysroot_libs = [] |
| |
| # Force-enable `--color=always` for rustc, even when it would be disabled for |
| # a platform. Mostly applicable to Windows, where new versions can handle ANSI |
| # escape sequences but it's not reliable in general. |
| force_rustc_color_output = false |
| } |
| |
| # Use the Rust toolchain built in-tree. When false, we use the prebuilt Rust |
| # stdlibs that come with the specified custom toolchain. |
| use_chromium_rust_toolchain = rust_sysroot_absolute == "" |
| |
| # Platform support for the Rust toolchain. |
| chromium_toolchain_supports_platform = !is_nacl && !is_wasm |
| custom_toolchain_supports_platform = !is_nacl || rust_toolchain_supports_nacl |
| |
| # Not all target triples (GN toolchains) are supported by the Rust compiler. |
| # Define if we support the current GN toolchain. |
| toolchain_has_rust = false |
| |
| # The rustc_revision is used to introduce a dependency on the toolchain version |
| # (so e.g. rust targets are rebuilt, and the standard library is re-copied when |
| # the toolchain changes). It is left empty for custom toolchains. |
| rustc_revision = "" |
| |
| if (enable_rust) { |
| if (use_chromium_rust_toolchain) { |
| toolchain_has_rust = chromium_toolchain_supports_platform |
| if (toolchain_has_rust) { |
| update_rust_args = [ "--print-package-version" ] |
| rustc_revision = exec_script("//tools/rust/update_rust.py", |
| update_rust_args, |
| "trim string") |
| } |
| |
| # The same as written in `config.toml.template`. |
| rust_channel = "dev" |
| } else { |
| toolchain_has_rust = custom_toolchain_supports_platform |
| rustc_revision = rustc_version |
| } |
| } |
| |
| # TODO(crbug.com/40809974): To build unit tests for Android we need to build |
| # them as a dylib and put them into an APK. We should reuse all the same logic |
| # for gtests from the `//testing/test:test` template. |
| can_build_rust_unit_tests = toolchain_has_rust && !is_android |
| |
| # We want to store rust_sysroot as a source-relative variable for ninja |
| # portability. In practice if an external toolchain was specified, it might |
| # be an absolute path, but we'll do our best. |
| if (enable_rust) { |
| if (use_chromium_rust_toolchain) { |
| rust_sysroot = "//third_party/rust-toolchain" |
| } else { |
| rust_sysroot = get_path_info(rust_sysroot_absolute, "abspath") |
| } |
| } |
| |
| # Figure out the Rust target triple (aka 'rust_abi_target') |
| # |
| # This is here rather than in the toolchain files because it's used also by |
| # //build/rust/std to find the Rust standard library and construct a sysroot for |
| # rustc invocations. |
| # |
| # The list of architectures supported by Rust is here: |
| # https://doc.rust-lang.org/nightly/rustc/platform-support.html. We map Chromium |
| # targets to Rust targets comprehensively despite not having official support |
| # (see '*_toolchain_supports_platform above') to enable experimentation with |
| # other toolchains. |
| # |
| # The `cargo_target_abi` is the `target_abi` given by Cargo to build scripts |
| # as the `CARGO_CFG_TARGET_ABI` environment variable. It is determined for |
| # each `rust_abi_target` by doing `cargo build --target $rust_abi_target` with |
| # a cargo project that dumps the `CARGO_CFG_TARGET_ABI` from its build.rs. See |
| # https://issues.chromium.org/u/1/issues/372512092#comment5 for an example. |
| rust_abi_target = "" |
| if (is_linux || is_chromeos) { |
| if (current_cpu == "arm64") { |
| rust_abi_target = "aarch64-unknown-linux-gnu" |
| cargo_target_abi = "" |
| } else if (current_cpu == "x86") { |
| rust_abi_target = "i686-unknown-linux-gnu" |
| cargo_target_abi = "" |
| } else if (current_cpu == "x64") { |
| rust_abi_target = "x86_64-unknown-linux-gnu" |
| cargo_target_abi = "" |
| } else if (current_cpu == "arm") { |
| if (arm_float_abi == "hard") { |
| float_suffix = "hf" |
| } else { |
| float_suffix = "" |
| } |
| if (arm_arch == "armv7-a" || arm_arch == "armv7") { |
| # We have no way to inform Rust about the -a suffix, so we end up |
| # targeting armv7 in both cases. |
| # |
| # We also try to propagate the availability of NEON without feature |
| # detection; in C++ this is done by -mfpu=neon, but in Rust we need to |
| # use a different ABI target. |
| # |
| # The thumbv7 vs. armv7 distinction is for legacy reasons and both |
| # targets in fact target Thumb, see: |
| # https://github.com/rust-lang/rust/issues/44722 |
| if (arm_use_neon) { |
| rust_abi_target = "thumbv7neon-unknown-linux-gnueabi" + float_suffix |
| } else { |
| rust_abi_target = "armv7-unknown-linux-gnueabi" + float_suffix |
| } |
| cargo_target_abi = "eabi" + float_suffix |
| } else { |
| rust_abi_target = "arm-unknown-linux-gnueabi" + float_suffix |
| cargo_target_abi = "eabi" + float_suffix |
| } |
| } else if (current_cpu == "riscv64") { |
| rust_abi_target = "riscv64gc-unknown-linux-gnu" |
| cargo_target_abi = "" |
| } else { |
| # Best guess for other future platforms. |
| rust_abi_target = current_cpu + "-unknown-linux-gnu" |
| cargo_target_abi = "" |
| } |
| } else if (is_android) { |
| import("//build/config/android/abi.gni") |
| if (android_abi_target == "i686-linux-android") { |
| rust_abi_target = android_abi_target |
| cargo_target_abi = "" |
| } else if (android_abi_target == "arm-linux-androideabi") { |
| # Android clang target specifications mostly match Rust, but this |
| # is an exception. |
| # See section above for Linux for thumbv7neon vs. armv7. |
| # Note that on Android, NEON is enabled for all builds except Cronet. |
| if (arm_use_neon) { |
| rust_abi_target = "thumbv7neon-linux-androideabi" |
| } else { |
| rust_abi_target = "armv7-linux-androideabi" |
| } |
| cargo_target_abi = "eabi" |
| } else if (android_abi_target == "mipsel-linux-android") { |
| # There is no MIPS android target. |
| rust_abi_target = "" |
| cargo_target_abi = "" |
| } else if (android_abi_target == "x86_64-linux-android") { |
| rust_abi_target = android_abi_target |
| cargo_target_abi = "" |
| } else if (android_abi_target == "aarch64-linux-android") { |
| rust_abi_target = android_abi_target |
| cargo_target_abi = "" |
| } else if (android_abi_target == "mips64el-linux-android") { |
| # There is no MIPS android target. |
| rust_abi_target = "" |
| cargo_target_abi = "" |
| } else if (android_abi_target == "riscv64-linux-android") { |
| rust_abi_target = android_abi_target |
| cargo_target_abi = "" |
| } else { |
| assert(false, "Unknown Android ABI: " + android_abi_target) |
| } |
| } else if (is_fuchsia) { |
| if (current_cpu == "arm64") { |
| rust_abi_target = "aarch64-unknown-fuchsia" |
| cargo_target_abi = "" |
| } else if (current_cpu == "x64") { |
| rust_abi_target = "x86_64-unknown-fuchsia" |
| cargo_target_abi = "" |
| } else { |
| assert(false, "Architecture not supported") |
| } |
| } else if (is_ios) { |
| if (current_cpu == "arm64") { |
| if (target_platform == "iphoneos") { |
| if (target_environment == "simulator") { |
| rust_abi_target = "aarch64-apple-ios-sim" |
| cargo_target_abi = "sim" |
| } else if (target_environment == "device") { |
| rust_abi_target = "aarch64-apple-ios" |
| cargo_target_abi = "" |
| } else if (target_environment == "catalyst") { |
| rust_abi_target = "aarch64-apple-ios-macabi" |
| cargo_target_abi = "macabi" |
| } else { |
| assert(false, "unsupported target_environment=$target_environment") |
| } |
| } else if (target_platform == "tvos") { |
| if (target_environment == "simulator") { |
| rust_abi_target = "aarch64-apple-tvos-sim" |
| cargo_target_abi = "sim" |
| } else if (target_environment == "device") { |
| rust_abi_target = "aarch64-apple-tvos" |
| cargo_target_abi = "" |
| } else { |
| assert(false, "unsupported target_environment=$target_environment") |
| } |
| } else { |
| assert(false, "unsupported target_platform=$target_platform") |
| } |
| } else if (current_cpu == "arm") { |
| rust_abi_target = "armv7s-apple-ios" |
| cargo_target_abi = "" |
| } else if (current_cpu == "x64") { |
| if (target_platform == "iphoneos") { |
| if (target_environment == "simulator") { |
| rust_abi_target = "x86_64-apple-ios" |
| cargo_target_abi = "sim" |
| } else if (target_environment == "catalyst") { |
| rust_abi_target = "x86_64-apple-ios-macabi" |
| cargo_target_abi = "macabi" |
| } else { |
| assert(false, "unsupported target_environment=$target_environment") |
| } |
| } else if (target_platform == "tvos") { |
| if (target_environment == "simulator") { |
| rust_abi_target = "x86_64-apple-tvos" |
| cargo_target_abi = "sim" |
| } else { |
| assert(false, "unsupported target_environment=$target_environment") |
| } |
| } else { |
| assert(false, "unsupported target_platform=$target_platform") |
| } |
| } else if (current_cpu == "x86") { |
| rust_abi_target = "i386-apple-ios" |
| } else { |
| assert(false, "Architecture not supported") |
| } |
| } else if (is_mac) { |
| if (current_cpu == "arm64") { |
| rust_abi_target = "aarch64-apple-darwin" |
| cargo_target_abi = "" |
| } else if (current_cpu == "x64") { |
| rust_abi_target = "x86_64-apple-darwin" |
| cargo_target_abi = "" |
| } else { |
| assert(false, "Architecture not supported") |
| } |
| } else if (is_win) { |
| if (current_cpu == "arm64") { |
| rust_abi_target = "aarch64-pc-windows-msvc" |
| cargo_target_abi = "" |
| } else if (current_cpu == "x64") { |
| rust_abi_target = "x86_64-pc-windows-msvc" |
| cargo_target_abi = "" |
| } else if (current_cpu == "x86") { |
| rust_abi_target = "i686-pc-windows-msvc" |
| cargo_target_abi = "" |
| } else { |
| assert(false, "Architecture not supported") |
| } |
| } |
| |
| assert(!toolchain_has_rust || rust_abi_target != "") |
| |
| # This variable is passed to the Rust libstd build. |
| rust_target_arch = "" |
| if (current_cpu == "x86") { |
| rust_target_arch = "x86" |
| } else if (current_cpu == "x64") { |
| rust_target_arch = "x86_64" |
| } else if (current_cpu == "arm") { |
| rust_target_arch = "arm" |
| } else if (current_cpu == "arm64") { |
| rust_target_arch = "aarch64" |
| } else if (current_cpu == "mipsel") { |
| rust_target_arch = "mips" |
| } else if (current_cpu == "mips64el") { |
| rust_target_arch = "mips64" |
| } else if (current_cpu == "s390x") { |
| rust_target_arch = "s390x" |
| } else if (current_cpu == "ppc64") { |
| rust_target_arch = "powerpc64" |
| } else if (current_cpu == "riscv64") { |
| rust_target_arch = "riscv64" |
| } |
| |
| assert(!toolchain_has_rust || rust_target_arch != "") |
| |
| # Arguments for Rust invocation. |
| # This is common between gcc/clang, Mac and Windows toolchains so specify once, |
| # here. This is not the complete command-line: toolchains should add -o |
| # and probably --emit arguments too. |
| rustc_common_args = "--crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}}" |
| |
| # Rust procedural macros are shared objects loaded into a prebuilt host rustc |
| # binary. To build them, we obviously need to build for the host. Not only |
| # that, but because the host rustc is prebuilt, it lacks the machinery to be |
| # able to load shared objects built using sanitizers (ASAN etc.). For that |
| # reason, we need to use a host toolchain that lacks sanitizers. Additionally, |
| # proc macros should use panic=unwind, which means they need a stdlib that is |
| # compiled the same way, as is the stdlib that we ship with the compiler. |
| if (toolchain_for_rust_host_build_tools) { |
| rust_macro_toolchain = current_toolchain |
| } else { |
| rust_macro_toolchain = "${host_toolchain}_for_rust_host_build_tools" |
| } |
| |
| # When this is true, a prebuilt Rust stdlib will be used. This has implications |
| # such as that the panic strategy (unwind, abort) must match how the stdlib is |
| # compiled, which is typically as unwind. |
| rust_prebuilt_stdlib = |
| !use_chromium_rust_toolchain || toolchain_for_rust_host_build_tools |