# 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 # /.rustup/toolchains/nightly-- 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(https://crbug.com/1482525): 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 = [] # Use goma for Rust builds. Experimental. The only known problem is # b/193072381, but then again, we don't expect a build speedup before much # more work is done. use_goma_rust = false # 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 Boringssl Rust bindings generation enable_rust_boringssl = 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