| # 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") |
| } |
| |
| declare_args() { |
| # Whether to allow Rust code to be part of the Chromium *build process*. |
| # This can be used to create Rust test binaries, even if the flag below |
| # is false. |
| # This only applies to Chromium itself, so the build_with_chromium check |
| # should not be removed. |
| # TODO(crbug.com/1386212): Mac |
| # TODO(crbug.com/1271215): Windows |
| # TODO(crbug.com/1426472): use_clang_coverage |
| # TODO(crbug.com/1427362): using_sanitizer |
| # TODO(crbug.com/1427364): target_cpu != "x86" |
| # There is no specific bug for !is_official_build or other platforms, since |
| # this is just a matter of rolling things out slowly and carefully and there |
| # may be no actual bugs there. |
| enable_rust = (is_linux || is_android) && !is_official_build && |
| !using_sanitizer && target_cpu != "x86" && |
| !use_clang_coverage && is_clang && 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 |
| |
| # Use the Rust toolchain built in-tree. See //tools/rust. |
| use_chromium_rust_toolchain = true |
| |
| # Build libstd locally with GN and use that instead of the prebuilts, where |
| # applicable. If this is false the prebuilt libstd will always be used. If |
| # true, the local build is only used with the Chromium Rust toolchain and only |
| # on supported platforms and GN targets. |
| enable_local_libstd = true |
| |
| # Chromium currently has a Rust toolchain for Android and Linux, but |
| # if you wish to experiment on more platforms you can use this |
| # argument to specify an alternative toolchain. |
| # This should be an absolute path to a directory |
| # containing a 'bin' directory and others. Commonly |
| # <home dir>/.rustup/toolchains/nightly-<something>-<something> |
| rust_sysroot_absolute = "" |
| |
| # If you're using an external Rust toolchain, set this to a Rust |
| # the output of rustc -V. |
| 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 |
| |
| # 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 |
| |
| # The host toolchain to use when you don't want sanitizers enabled. By default |
| # it is the regular toolchain, but when that toolchain has sanitizers, then |
| # this variable is changed to avoid them. |
| host_toolchain_no_sanitizers = host_toolchain |
| } |
| |
| declare_args() { |
| # Use a separate declare_args so these variables' defaults can depend on the |
| # ones above. |
| |
| # When true, uses the locally-built std in all Rust targets. |
| # |
| # As an internal implementation detail this can be overridden on specific |
| # targets (e.g. to run build.rs scripts while building std), but this |
| # generally should not be done. |
| use_local_std_by_default = enable_local_libstd && use_chromium_rust_toolchain |
| |
| # Individual Rust components. |
| |
| # Conversions between Rust types and C++ types. |
| enable_rust_base_conversions = enable_all_rust_features |
| |
| # The base::JSONReader implementation. Requires base conversions. |
| enable_rust_json = enable_all_rust_features |
| |
| # Support for chrome://crash-rust to check crash dump collection works. |
| enable_rust_crash = enable_all_rust_features |
| |
| # Support for Rust mojo bindings. |
| enable_rust_mojo = enable_all_rust_features |
| |
| # Support for the 'gnrt' Rust tool. |
| enable_rust_gnrt = enable_all_rust_features |
| |
| # Rust gtest interop |
| enable_rust_gtest_interop = enable_all_rust_features |
| |
| # Enable Boringssl Rust bindings generation |
| enable_rust_boringssl = enable_all_rust_features |
| } |
| |
| # Platform support for "official" toolchains (Android or Chromium) |
| android_toolchain_supports_platform = |
| (!is_nacl && |
| (is_android && (current_cpu == "arm" || current_cpu == "arm64" || |
| current_cpu == "x64" || current_cpu == "x86"))) || |
| (is_linux && current_cpu == "x64") |
| chromium_toolchain_supports_platform = !is_nacl |
| custom_toolchain_supports_platform = !is_nacl || rust_toolchain_supports_nacl |
| |
| toolchain_has_rust = |
| enable_rust && |
| ((use_chromium_rust_toolchain && chromium_toolchain_supports_platform) || |
| (!use_chromium_rust_toolchain && android_toolchain_supports_platform) || |
| (rust_sysroot_absolute != "" && custom_toolchain_supports_platform)) |
| |
| # 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 (toolchain_has_rust) { |
| if (use_chromium_rust_toolchain) { |
| update_rust_args = [ "--print-package-version" ] |
| rustc_revision = exec_script("//tools/rust/update_rust.py", |
| update_rust_args, |
| "trim string") |
| } else if (rust_sysroot_absolute != "") { |
| rustc_revision = rustc_version |
| } else { |
| # Android toolchain version. |
| rustc_revision = "rustc 1.64.0-dev (Android Rust Toolchain version 9099361)" |
| } |
| } |
| |
| # 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 |
| |
| # Whether to build chrome://crash/rust support. |
| build_rust_crash = toolchain_has_rust && enable_rust_crash |
| |
| # 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 (rust_sysroot_absolute != "") { |
| rust_sysroot = get_path_info(rust_sysroot_absolute, "abspath") |
| use_unverified_rust_toolchain = true |
| } else if (use_chromium_rust_toolchain) { |
| rust_sysroot = "//third_party/rust-toolchain" |
| use_unverified_rust_toolchain = false |
| } else { |
| if (host_os != "linux") { |
| assert(false, |
| "Attempt to use Android Rust toolchain on an unsupported platform") |
| } |
| |
| rust_sysroot = "//third_party/android_rust_toolchain/toolchain" |
| use_unverified_rust_toolchain = false |
| extra_sysroot_libs += [ "libunwind.a" ] |
| } |
| } |
| |
| # 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) { |
| cpu = current_cpu |
| if (cpu == "arm64") { |
| cpu = "aarch64" |
| } else if (cpu == "x64") { |
| cpu = "x86_64" |
| } |
| rust_abi_target = 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") { |
| 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") { |
| 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 == "x86" || current_cpu == "x64") { |
| rust_abi_target = "x86_64-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 != "") |
| |
| # Must use Chromium Rust toolchain to get precisely matching LLVM versions |
| # in order to enable LTO. Some say that LTO probably works if LLVM is "close |
| # enough", but we don't want to take that risk. |
| assert(!use_thin_lto || !enable_rust || use_chromium_rust_toolchain || |
| use_unverified_rust_toolchain, |
| "Must use Chromium Rust toolchain for LTO") |
| |
| # Determine whether the local libstd can and should be built. |
| local_libstd_supported = enable_local_libstd && use_chromium_rust_toolchain |
| |
| # Determine whether the prebuilt libstd can be used |
| prebuilt_libstd_supported = !use_chromium_rust_toolchain || |
| (target_os == "linux" && target_cpu == "x64") |
| |
| # 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. This is only strictly necessary |
| # for procedural macros, but we may also choose to build standalone Rust host |
| # executable tools using the same toolchain, as they're likely to depend upon |
| # similar dependencies (syn, quote etc.) and it saves a little build time. |
| if (using_sanitizer || toolchain_disables_sanitizers) { |
| host_toolchain_no_sanitizers = "${host_toolchain}_no_sanitizers" |
| } |