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