1# Copyright 2021 The Chromium Project. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import("//build/config/chrome_build.gni") 6import("//build/config/compiler/compiler.gni") 7import("//build/config/sanitizers/sanitizers.gni") 8import("//build/toolchain/toolchain.gni") 9 10if (is_android) { 11 import("//build/config/android/config.gni") 12} 13 14if (is_ios) { 15 import("//build/config/ios/config.gni") # For `target_environment` 16 import("//build/config/ios/ios_sdk.gni") # For `xcode_version_int` 17} 18 19declare_args() { 20 # Rust is available in the Chromium build but 3p repos that use //build may 21 # not use Rust and thus won't want to depend on having the Rust toolchain 22 # present, so this defaults to off in those cases. 23 # 24 # Chromium-based projects that are built for for architectures Chrome does not 25 # support may need to disable this as well, though they may need to replace 26 # code with C/C++ to get a functional product. 27 enable_rust = build_with_chromium 28 29 # The CXX tool is in //third_party/rust which is not shared with downstream 30 # projects yet. So they need to copy the required dependencies and GN files 31 # into their project to enable CXX there. 32 enable_cxx = build_with_chromium 33 34 # As we incrementally enable Rust on mainstream builders, we want to enable 35 # the toolchain (by switching 'enable_rust' to true) while still disabling 36 # almost all Rust features). Yet we still want to have some builders with 37 # all Rust features enabled. 38 enable_all_rust_features = false 39 40 # Chromium provides a Rust toolchain in //third_party/rust-toolchain when 41 # checkout_rust is True (which is being rolled out by default over time). 42 # 43 # To use a custom toolchain instead, specify an absolute path to the root of 44 # a Rust sysroot, which will have a 'bin' directory and others. Commonly 45 # <home dir>/.rustup/toolchains/nightly-<something>-<something> 46 rust_sysroot_absolute = "" 47 48 # If you're using a Rust toolchain as specified by rust_sysroot_absolute, 49 # set this to the output of `rustc -V`. Changing this string will cause all 50 # Rust targets to be rebuilt, which allows you to update your toolchain and 51 # not break incremental builds. 52 rustc_version = "" 53 54 # If you're using a Rust toolchain as specified by rust_sysroot_absolute, 55 # you can specify whether it supports nacl here. 56 rust_toolchain_supports_nacl = false 57 58 # Any extra std rlibs in your Rust toolchain, relative to the standard 59 # Rust toolchain. Typically used with 'rust_sysroot_absolute' 60 added_rust_stdlib_libs = [] 61 62 # Any removed std rlibs in your Rust toolchain, relative to the standard 63 # Rust toolchain. Typically used with 'rust_sysroot_absolute' 64 removed_rust_stdlib_libs = [] 65 66 # Non-rlib libs provided in the toolchain sysroot. Usually this is empty, but 67 # e.g. the Android Rust Toolchain provides a libunwind.a that rustc expects. 68 extra_sysroot_libs = [] 69 70 # Use goma for Rust builds. Experimental. The only known problem is 71 # b/193072381, but then again, we don't expect a build speedup before much 72 # more work is done. 73 use_goma_rust = false 74 75 # Force-enable `--color=always` for rustc, even when it would be disabled for 76 # a platform. Mostly applicable to Windows, where new versions can handle ANSI 77 # escape sequences but it's not reliable in general. 78 force_rustc_color_output = false 79} 80 81# Use a separate declare_args so these variables' defaults can depend on the 82# ones above. 83declare_args() { 84 # Individual Rust components. 85 86 # Conversions between Rust types and C++ types. 87 enable_rust_base_conversions = enable_rust 88 89 # The base::JSONReader implementation. Requires base conversions. 90 enable_rust_json = enable_rust && enable_all_rust_features 91 92 # Support for chrome://crash-rust to check crash dump collection works. 93 enable_rust_crash = enable_rust 94 95 # Support for Rust mojo bindings. 96 enable_rust_mojo = enable_rust && enable_all_rust_features 97 98 # Rust gtest interop. 99 enable_rust_gtest_interop = enable_rust 100 101 # Enable Boringssl Rust bindings generation 102 enable_rust_boringssl = enable_rust && enable_all_rust_features 103 104 # Enable experimental Fontations Rust font stack. 105 use_typeface_fontations = enable_rust 106} 107 108# Use the Rust toolchain built in-tree. When false, we use the prebuilt Rust 109# stdlibs that come with the specified custom toolchain. 110use_chromium_rust_toolchain = rust_sysroot_absolute == "" 111 112# Platform support for the Rust toolchain. 113chromium_toolchain_supports_platform = !is_nacl 114custom_toolchain_supports_platform = !is_nacl || rust_toolchain_supports_nacl 115 116# Not all target triples (GN toolchains) are supported by the Rust compiler. 117# Define if we support the current GN toolchain. 118toolchain_has_rust = false 119 120# The rustc_revision is used to introduce a dependency on the toolchain version 121# (so e.g. rust targets are rebuilt, and the standard library is re-copied when 122# the toolchain changes). It is left empty for custom toolchains. 123rustc_revision = "" 124 125if (enable_rust) { 126 if (use_chromium_rust_toolchain) { 127 toolchain_has_rust = chromium_toolchain_supports_platform 128 if (toolchain_has_rust) { 129 update_rust_args = [ "--print-package-version" ] 130 rustc_revision = exec_script("//tools/rust/update_rust.py", 131 update_rust_args, 132 "trim string") 133 } 134 135 # The same as written in `config.toml.template`. 136 rust_channel = "dev" 137 } else { 138 toolchain_has_rust = custom_toolchain_supports_platform 139 rustc_revision = rustc_version 140 } 141} 142 143# TODO(crbug.com/1278030): To build unit tests for Android we need to build 144# them as a dylib and put them into an APK. We should reuse all the same logic 145# for gtests from the `//testing/test:test` template. 146can_build_rust_unit_tests = toolchain_has_rust && !is_android 147 148# Whether artifacts produced by the Rust compiler can participate in ThinLTO. 149# 150# One important consideration is whether the linker uses the same LLVM 151# version as `rustc` (i.e. if it can understand the LLVM-IR from the 152# compilation artifacts produced by `rustc`). In LaCrOS and ash builds this may 153# not be true - see b/299483903. 154# 155# TODO(https://crbug.com/1482525): Re-enable ThinLTO for Rust on LaCrOS 156# TODO(b/300937673): Re-enable ThinLTO for Rust on ash-chrome 157toolchain_supports_rust_thin_lto = !is_chromeos 158 159# We want to store rust_sysroot as a source-relative variable for ninja 160# portability. In practice if an external toolchain was specified, it might 161# be an absolute path, but we'll do our best. 162if (enable_rust) { 163 if (use_chromium_rust_toolchain) { 164 rust_sysroot = "//third_party/rust-toolchain" 165 } else { 166 rust_sysroot = get_path_info(rust_sysroot_absolute, "abspath") 167 } 168 169 # Prebuilt toolchains won't come with bindgen, so we unconditionally use the 170 # bindgen we ship with the Rust toolchain. This could be made configurable 171 # if folks want to supply a bindgen with their toolchain. 172 rust_bindgen_root = "//third_party/rust-toolchain" 173} 174 175# Figure out the Rust target triple (aka 'rust_abi_target') 176# 177# This is here rather than in the toolchain files because it's used also by 178# //build/rust/std to find the Rust standard library and construct a sysroot for 179# rustc invocations. 180# 181# The list of architectures supported by Rust is here: 182# https://doc.rust-lang.org/nightly/rustc/platform-support.html. We map Chromium 183# targets to Rust targets comprehensively despite not having official support 184# (see '*_toolchain_supports_platform above') to enable experimentation with 185# other toolchains. 186rust_abi_target = "" 187if (is_linux || is_chromeos) { 188 if (current_cpu == "arm64") { 189 rust_abi_target = "aarch64-unknown-linux-gnu" 190 } else if (current_cpu == "x86") { 191 rust_abi_target = "i686-unknown-linux-gnu" 192 } else if (current_cpu == "x64") { 193 rust_abi_target = "x86_64-unknown-linux-gnu" 194 } else if (current_cpu == "arm") { 195 if (arm_float_abi == "hard") { 196 float_suffix = "hf" 197 } else { 198 float_suffix = "" 199 } 200 if (arm_arch == "armv7-a" || arm_arch == "armv7") { 201 # No way to inform Rust about the -a suffix. 202 rust_abi_target = "armv7-unknown-linux-gnueabi" + float_suffix 203 } else { 204 rust_abi_target = "arm-unknown-linux-gnueabi" + float_suffix 205 } 206 } else { 207 # Best guess for other future platforms. 208 rust_abi_target = current_cpu + "-unknown-linux-gnu" 209 } 210} else if (is_android) { 211 import("//build/config/android/abi.gni") 212 rust_abi_target = android_abi_target 213 if (rust_abi_target == "arm-linux-androideabi") { 214 # Android clang target specifications mostly match Rust, but this 215 # is an exception 216 rust_abi_target = "armv7-linux-androideabi" 217 } 218} else if (is_fuchsia) { 219 if (current_cpu == "arm64") { 220 rust_abi_target = "aarch64-fuchsia" 221 } else if (current_cpu == "x64") { 222 rust_abi_target = "x86_64-fuchsia" 223 } else { 224 assert(false, "Architecture not supported") 225 } 226} else if (is_ios) { 227 if (current_cpu == "arm64") { 228 if (target_environment == "simulator") { 229 rust_abi_target = "aarch64-apple-ios-sim" 230 } else if (target_environment == "catalyst") { 231 rust_abi_target = "aarch64-apple-ios-macabi" 232 } else { 233 rust_abi_target = "aarch64-apple-ios" 234 } 235 } else if (current_cpu == "arm") { 236 # There's also an armv7s-apple-ios, which targets a more recent ARMv7 237 # generation CPU found in later iPhones. We'll go with the older one for 238 # maximal compatibility. As we come to support all the different platforms 239 # with Rust, we might want to be more precise here. 240 rust_abi_target = "armv7-apple-ios" 241 } else if (current_cpu == "x64") { 242 if (target_environment == "catalyst") { 243 rust_abi_target = "x86_64-apple-ios-macabi" 244 } else { 245 rust_abi_target = "x86_64-apple-ios" 246 } 247 } else if (current_cpu == "x86") { 248 rust_abi_target = "i386-apple-ios" 249 } else { 250 assert(false, "Architecture not supported") 251 } 252} else if (is_mac) { 253 if (current_cpu == "arm64") { 254 rust_abi_target = "aarch64-apple-darwin" 255 } else if (current_cpu == "x64") { 256 rust_abi_target = "x86_64-apple-darwin" 257 } else { 258 assert(false, "Architecture not supported") 259 } 260} else if (is_win) { 261 if (current_cpu == "arm64") { 262 rust_abi_target = "aarch64-pc-windows-msvc" 263 } else if (current_cpu == "x64") { 264 rust_abi_target = "x86_64-pc-windows-msvc" 265 } else if (current_cpu == "x86") { 266 rust_abi_target = "i686-pc-windows-msvc" 267 } else { 268 assert(false, "Architecture not supported") 269 } 270} 271 272assert(!toolchain_has_rust || rust_abi_target != "") 273 274# This variable is passed to the Rust libstd build. 275rust_target_arch = "" 276if (current_cpu == "x86") { 277 rust_target_arch = "x86" 278} else if (current_cpu == "x64") { 279 rust_target_arch = "x86_64" 280} else if (current_cpu == "arm") { 281 rust_target_arch = "arm" 282} else if (current_cpu == "arm64") { 283 rust_target_arch = "aarch64" 284} else if (current_cpu == "mipsel") { 285 rust_target_arch = "mips" 286} else if (current_cpu == "mips64el") { 287 rust_target_arch = "mips64" 288} else if (current_cpu == "s390x") { 289 rust_target_arch = "s390x" 290} else if (current_cpu == "ppc64") { 291 rust_target_arch = "powerpc64" 292} else if (current_cpu == "riscv64") { 293 rust_target_arch = "riscv64" 294} 295 296assert(!toolchain_has_rust || rust_target_arch != "") 297 298# Arguments for Rust invocation. 299# This is common between gcc/clang, Mac and Windows toolchains so specify once, 300# here. This is not the complete command-line: toolchains should add -o 301# and probably --emit arguments too. 302rustc_common_args = "--crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}}" 303 304# Rust procedural macros are shared objects loaded into a prebuilt host rustc 305# binary. To build them, we obviously need to build for the host. Not only 306# that, but because the host rustc is prebuilt, it lacks the machinery to be 307# able to load shared objects built using sanitizers (ASAN etc.). For that 308# reason, we need to use a host toolchain that lacks sanitizers. Additionally, 309# proc macros should use panic=unwind, which means they need a stdlib that is 310# compiled the same way, as is the stdlib that we ship with the compiler. 311if (toolchain_for_rust_host_build_tools) { 312 rust_macro_toolchain = current_toolchain 313} else { 314 rust_macro_toolchain = "${host_toolchain}_for_rust_host_build_tools" 315} 316 317# When this is true, a prebuilt Rust stdlib will be used. This has implications 318# such as that the panic strategy (unwind, abort) must match how the stdlib is 319# compiled, which is typically as unwind. 320rust_prebuilt_stdlib = 321 !use_chromium_rust_toolchain || toolchain_for_rust_host_build_tools 322