blob: b6e0822b68c3f2289e1737b8e4c2db8348a9452d [file] [log] [blame]
# 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) {
import("//build/config/ios/config.gni") # For `target_environment`
import("//build/config/ios/ios_sdk.gni") # For `xcode_version_int`
}
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.
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.
enable_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.
enable_chromium_prelude = build_with_chromium
# As we incrementally enable Rust on mainstream builders, we want to enable
# the toolchain (by switching 'enable_rust' to true) while still disabling
# almost all Rust features). Yet we still want to have some builders with
# all Rust features enabled.
enable_all_rust_features = false
# 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 = ""
# 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 a separate declare_args so these variables' defaults can depend on the
# ones above.
declare_args() {
# Individual Rust components.
# Conversions between Rust types and C++ types.
enable_rust_base_conversions = enable_rust
# The base::JSONReader implementation. Requires base conversions.
enable_rust_json = enable_rust && enable_all_rust_features
# Support for chrome://crash-rust to check crash dump collection works.
enable_rust_crash = enable_rust
# Support for Rust mojo bindings.
enable_rust_mojo = enable_rust && enable_all_rust_features
# Rust gtest interop.
enable_rust_gtest_interop = enable_rust
# Enable experimental Fontations Rust font stack.
use_typeface_fontations = enable_rust
}
# 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
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/1278030): 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")
}
# Prebuilt toolchains won't come with bindgen, so we unconditionally use the
# bindgen we ship with the Rust toolchain. This could be made configurable
# if folks want to supply a bindgen with their toolchain.
rust_bindgen_root = "//third_party/rust-toolchain"
}
# 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.
rust_abi_target = ""
if (is_linux || is_chromeos) {
if (current_cpu == "arm64") {
rust_abi_target = "aarch64-unknown-linux-gnu"
} else if (current_cpu == "x86") {
rust_abi_target = "i686-unknown-linux-gnu"
} else if (current_cpu == "x64") {
rust_abi_target = "x86_64-unknown-linux-gnu"
} else if (current_cpu == "arm") {
if (arm_float_abi == "hard") {
float_suffix = "hf"
} else {
float_suffix = ""
}
if (arm_arch == "armv7-a" || arm_arch == "armv7") {
# No way to inform Rust about the -a suffix.
rust_abi_target = "armv7-unknown-linux-gnueabi" + float_suffix
} else {
rust_abi_target = "arm-unknown-linux-gnueabi" + float_suffix
}
} else {
# Best guess for other future platforms.
rust_abi_target = current_cpu + "-unknown-linux-gnu"
}
} else if (is_android) {
import("//build/config/android/abi.gni")
rust_abi_target = android_abi_target
if (rust_abi_target == "arm-linux-androideabi") {
# Android clang target specifications mostly match Rust, but this
# is an exception
rust_abi_target = "armv7-linux-androideabi"
}
} else if (is_fuchsia) {
if (current_cpu == "arm64") {
rust_abi_target = "aarch64-fuchsia"
} else if (current_cpu == "x64") {
rust_abi_target = "x86_64-fuchsia"
} else {
assert(false, "Architecture not supported")
}
} else if (is_ios) {
if (current_cpu == "arm64") {
if (target_environment == "simulator") {
rust_abi_target = "aarch64-apple-ios-sim"
} else if (target_environment == "catalyst") {
rust_abi_target = "aarch64-apple-ios-macabi"
} else {
rust_abi_target = "aarch64-apple-ios"
}
} else if (current_cpu == "arm") {
# There's also an armv7s-apple-ios, which targets a more recent ARMv7
# generation CPU found in later iPhones. We'll go with the older one for
# maximal compatibility. As we come to support all the different platforms
# with Rust, we might want to be more precise here.
rust_abi_target = "armv7-apple-ios"
} else if (current_cpu == "x64") {
if (target_environment == "catalyst") {
rust_abi_target = "x86_64-apple-ios-macabi"
} else {
rust_abi_target = "x86_64-apple-ios"
}
} 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"
} else if (current_cpu == "x64") {
rust_abi_target = "x86_64-apple-darwin"
} else {
assert(false, "Architecture not supported")
}
} else if (is_win) {
if (current_cpu == "arm64") {
rust_abi_target = "aarch64-pc-windows-msvc"
} else if (current_cpu == "x64") {
rust_abi_target = "x86_64-pc-windows-msvc"
} else if (current_cpu == "x86") {
rust_abi_target = "i686-pc-windows-msvc"
} 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