| # Rust Build Errors Guide | |
| This document lists Rust-related build errors that are noteworthy in the context | |
| of Chromium builds. | |
| [TOC] | |
| ## Unsafe Rust | |
| Chromium configures its compiler to disallow `unsafe` Rust by default. | |
| Unexpected `unsafe` Rust can cause build errors below: | |
| ``` | |
| error: usage of an `unsafe` block | |
| error: declaration of an `unsafe` function | |
| error: implementation of an `unsafe` trait | |
| error: implementation of an `unsafe` method | |
| ... | |
| note: requested on the command line with `-F unsafe-code` | |
| ``` | |
| `unsafe` Rust is [disallowed by default](/docs/rust/unsafe.md) to: | |
| * Discourage using `unsafe` Rust code | |
| * Make code reviews easier (e.g. `//third_party/rust` crates with | |
| `allow_unsafe = false` can get a bit less scrutiny). | |
| To fix the errors above you can either: | |
| * Express the same code in safe Rust if possible | |
| (e.g. using | |
| `slice[i]` or | |
| [`slice.get(i)`](https://doc.rust-lang.org/std/primitive.slice.html#method.get) | |
| rather than | |
| [`slice.get_unchecked(i)`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked), | |
| unless disassembly results show that the compiler cannot elide the checks | |
| and/or performance measurements show significant runtime difference) | |
| * Allow `unsafe` code in the given crate (ideally only for a small, | |
| easy-to-reason-about crate that encapsulates the unsafety behind a safe public | |
| API). | |
| * In manually-authored `BUILD.gn` files (e.g. in first-party code) you can | |
| set `allow_unsafe = true` in `rust_static_library` | |
| * In `gnrt`-generated `BUILD.gn` files you can | |
| set `extra_kv.allow_unsafe` property to `true` in | |
| `third_party/rust/chromium_crates_io/gnrt_config.toml` (and then | |
| regenerate `BUILD.gn` with `tools/crates/run_gnrt.py gen`). | |
| ## Unstable features | |
| Chromium builds require an explicit opt-in to use unstable Rust features | |
| (see the policy in `//docs/rust/unstable_rust_feature_usage.md`). | |
| Unexpected usage of unstable Rust features can cause build errors below: | |
| ``` | |
| error[E0725]: the feature `feature_name` is not in the list of allowed features | |
| error[E0658]: use of unstable library feature `feature_name` | |
| ... | |
| note: see issue #XXXXX <https://github.com/rust-lang/rust/issues/XXXXX> for more information | |
| help: add `#![feature(feature_name)]` to the crate attributes to enable | |
| ``` | |
| To opt into allowing certain unstable features, you need to: | |
| * Opt into allowing an unstable feature in the `BUILD.gn` of a Rust crate | |
| (justifying edits to the policy in | |
| `//docs/rust/unstable_rust_feature_usage.md` as needed) | |
| * In manually-authored `BUILD.gn` files (e.g. in first-party code) you can | |
| set the following properties of `rust_static_library`: | |
| * `rustflags = [ "-Zallow-features=feature_name" ]` | |
| * `configs -= [ "//build/config/compiler:disallow_unstable_features" ]` | |
| * In `gnrt`-generated `BUILD.gn` files you can | |
| set `extra_kv.allow_unstable_features` property in | |
| `third_party/rust/chromium_crates_io/gnrt_config.toml` to the list of | |
| allowed feature names (and then | |
| regenerate `BUILD.gn` with `tools/crates/run_gnrt.py gen`). | |
| * Opt into allowing an unstable feature in the root module of a Rust crate. | |
| To do this add `#![feature(feature_name)]` to `lib.rs`. See also: | |
| * The brief | |
| [language reference documentation](https://doc.rust-lang.org/reference/attributes.html#:~:text=feature%20%E2%80%94%20Used%20to%20enable%20unstable%20or%20experimental%20compiler%20features.) | |
| of the `feature` attribute | |
| * An example usage in | |
| [the Unstable Book](https://doc.rust-lang.org/unstable-book/index.html) | |
| ## Missing sources | |
| `gn` and `ninja` know about build target inputs and sources through `input` | |
| and/or `sources` properties specified in `BUILD.gn` files. | |
| `rustc` independently discovers all `.rs` files by starting from a crate | |
| root, and then following `mod foo;` declarations. | |
| Chromium build will report an error when those 2 sources of information | |
| are out of sync - for example: | |
| ``` | |
| ERROR: Rust source file or input not in GN sources: ../../foo/bar/baz.rs | |
| ``` | |
| To fix errors like the one above | |
| you should ensure that the `BUILD.gn` lists the same source files and inputs | |
| as the ones actually used in `.rs` source code: | |
| * In manually-authored `BUILD.gn` files (e.g. in first-party code) you should | |
| double-check the `sources` property (or the `inputs` property in less common | |
| cases like when using | |
| [`include!`](https://doc.rust-lang.org/std/macro.include.html) macro). | |
| * TODO(lukasza): Figure out if/why it matters whether an `.rs` or `.rs.incl` | |
| file is listed in `sources` vs `inputs`. | |
| * In `gnrt`-generated `BUILD.gn` files, `gnrt` typically can discover all | |
| `.rs` files on its own, but sometimes `gnrt` may need extra crate metadata | |
| that you can provide via `gnrt_config.toml` - for example: | |
| * `extra_input_roots` can list source files | |
| to append to `sources` / `inputs` for the main Rust target | |
| * `extra_build_script_input_roots` | |
| can list sources files to append to `sources` / `inputs` | |
| for the `build.rs` script | |
| * See a comment at the top of `gnrt_config.toml` for more information | |
| * After editing `gnrt_config.toml` run | |
| `tools/crates/run_gnrt.py gen` to regenerate `BUILD.gn` files. | |
| ## Can't find and include `build.rs` output | |
| Third-party crates may depend on `build.rs` output - typically through | |
| `include!` of one or more files from the `env!("OUT_DIR")` directory. | |
| If `gn` and `ninja` are not aware of these `build.rs` outputs, then it may | |
| lead to build errors like the one: | |
| ``` | |
| --> ../../third_party/rust/chromium_crates_io/vendor/rustversion-v1/src/lib.rs:217:30 | |
| | | |
| 217 | const RUSTVERSION: Version = include!(concat!(env!("OUT_DIR"), "/version.expr")); | |
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | |
| | | |
| --> library/core/src/macros/mod.rs:1487:4 | |
| | | |
| = note: in this expansion of `include!` | |
| ``` | |
| To fix the error above: | |
| * check if `build_script_outputs` in `gnrt_config.toml` lists | |
| all `build.rs` outputs. | |
| * See a comment at the top of `gnrt_config.toml` for more information | |
| * After editing `gnrt_config.toml` run | |
| `tools/crates/run_gnrt.py gen` to regenerate `BUILD.gn` files. | |
| ## Dependency not visible to an internal Rust target | |
| Rust target templates like `rust_static_library("some_target")` | |
| internally expand into multiple smaller targets | |
| (e.g. a `rust_library` for invoking `rustc`, | |
| an `action` for invoking `clippy-driver`, | |
| `cxx`-supporting targets, etc.). | |
| This may cause `gn gen` errors when a dependency is exposed to the main | |
| target (e.g. `":some_target"`), but not to the internal targets (e.g. | |
| `":some_target_clippy"` or `":some_target_generator"`). | |
| Example error: | |
| ``` | |
| $ gn gen out/Default | |
| ERROR at //build/rust/gni_impl/rust_target.gni:587:9: Dependency not allowed. | |
| action("${_clippy_target_name}") { | |
| ^--------------------------------- | |
| The item //foo/bar:some_target_clippy | |
| can not depend on //foo/bar:internal_impl | |
| because it is not in //foo/bar:internal_impl's visibility list: [ | |
| //foo/bar:internal_target1 | |
| //foo/bar:internal_target2 | |
| ] | |
| ``` | |
| To fix the error above, we recommend the following approach to | |
| `visibility` declarations in `BUILD.gn` files: | |
| * Public targets should use unrestricted `visibility` | |
| * Private targets should restrict their `visibility` | |
| to specific directories - e.g. `visibility = [ ":*" ]` | |
| * Avoid restricting target `visibility` to specific, individual | |
| targets - e.g. do **not** say `visibility = [ ":some_target" ]`. | |
| Note: Other fix approaches have been discussed with | |
| [`@gn-dev` here](https://groups.google.com/a/chromium.org/g/gn-dev/c/8cUBSIsd8Qw/m/32uA6L1iCAAJ). |