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