blob: 4656805f2dfee6ffbd3fa9d957cb3eaddbe43683 [file] [log] [blame] [view]
danakj6e25f742022-12-01 21:47:421# Rust in Chromium
2
3[TOC]
4
5# Why?
6
danakjbb4d0c772023-10-13 13:22:287Handling untrustworthy data in non-trivial ways is a major source of security
8bugs, and it's therefore against Chromium's security policies
9[to do it in the Browser or Gpu process](../docs/security/rule-of-2.md) unless
10you are working in a memory-safe language.
danakj6e25f742022-12-01 21:47:4211
12Rust provides a cross-platform memory-safe language so that all platforms can
13handle untrustworthy data directly from a privileged process, without the
14performance overheads and complexity of a utility process.
15
danakj6e25f742022-12-01 21:47:4216# Status
17
danakjbb4d0c772023-10-13 13:22:2818The Rust toolchain is enabled for and supports all platforms and development
19environments that are supported by the Chromium project. The first milestone
20to include full production-ready support was M119.
danakj6e25f742022-12-01 21:47:4221
danakjbb4d0c772023-10-13 13:22:2822Rust is approved by Chrome ATLs for production use in
23[certain third-party scenarios](../docs/adding_to_third_party.md#Rust).
danakj6e25f742022-12-01 21:47:4224
25For questions or help, reach out to `[email protected]` or `#rust` on the
26[Chromium Slack](https://www.chromium.org/developers/slack/).
27
danakj6e25f742022-12-01 21:47:4228If you use VSCode, we have [additional advice below](#using-vscode).
29
danakjbb4d0c772023-10-13 13:22:2830# Adding a third-party Rust library
danakj6e25f742022-12-01 21:47:4231
danakjbb4d0c772023-10-13 13:22:2832Third-party libraries are pulled from [crates.io](https://crates.io), but
33Chromium does not use Cargo as a build system.
danakj6e25f742022-12-01 21:47:4234
35## Third-party review
36
danakj6e25f742022-12-01 21:47:4237All third-party crates need to go through third-party review. See
38[//docs/adding_to_third_party.md](adding_to_third_party.md) for instructions on
39how to have a library reviewed.
40
danakjbb4d0c772023-10-13 13:22:2841## Importing a crate from crates.io
42
danakj0ec93d12023-11-17 16:12:2343The `//third_party/rust/chromium_crates_io/Cargo.toml` file defines the set of crates
danakjbb4d0c772023-10-13 13:22:2844depended on from first-party code. Any transitive dependencies will be found
danakj0ec93d12023-11-17 16:12:2345from those listed there. The file is a [standard `Cargo.toml` file](
46https://doc.rust-lang.org/cargo/reference/manifest.html), though the crate
47itself is never built, it is only used to collect dependencies through the
48`[dependencies]` section.
danakjbb4d0c772023-10-13 13:22:2849
danakj9535a9c02024-01-12 20:14:5950These instructions require the presence of nightly `cargo` which is normally found
51in `//third_party/rust-toolchain/bin`. But [on Mac Arm](https://crbug.com/1515913)
52it is missing, and will need to be installed separately with
53[`rustup install nightly`](https://rustup.rs/) and added to the `PATH` environment.
54
danakj0ec93d12023-11-17 16:12:2355To use a third-party crate "bar" version 3 from first party code:
danakj98bec162023-11-21 14:55:02561. Change directory to the root `src/` dir of Chromium.
571. Add the crate to `//third_party/rust/chromium_crates_io/Cargo.toml`:
58 * `vpython3 ./tools/crates/run_gnrt.py add foo` to add the latest version of `foo`.
59 * `vpython3 ./tools/crates/run_gnrt.py add [email protected]` to add a specific version of `foo`.
60 * Or, directly through (nightly) cargo:
61 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt add foo`
62 * Or, edit the Cargo.toml by hand, finding the version you want from [crates.io](https://crates.io).
631. Download the crate's files:
64 * `./tools/crates/run_gnrt.py vendor` to download the new crate.
65 * Or, directly through (nightly) cargo:
danakj0ec93d12023-11-17 16:12:2366 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor`
danakjf509caa2023-11-23 15:29:4367 * This will also apply any patches in `//third_party/rust/chromium_crates_io/patches`
68 for the crates. If a patch can not apply, the crate's download will be cancelled and
69 an error will be printed. See [patching errors](#patching-errors) below for how to resolve
70 this.
danakj98bec162023-11-21 14:55:02711. Add the new files to git:
72 * `git add -f third_party/rust/chromium_crates_io/vendor`
73 * The `-f` is important, as files may be skipped otherwise from a
74 `.gitignore` inside the crate.
danakj98bec162023-11-21 14:55:02751. (optional) If the crate is only to be used by tests and tooling, then
76 specify the `"test"` group in `//third_party/rust/chromium_crates_io/gnrt_config.toml`:
77 ```
78 [crate.foo]
79 group = "test"
80 ```
811. Generate the `BUILD.gn` file for the new crate:
82 * `vpython3 ./tools/crates/run_gnrt.py gen`
83 * Or, directly through (nightly) cargo:
84 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`
danakjaed1daf2024-01-05 17:44:32851. Verify if all new dependencies are already audited by running `cargo vet`:
danakj9535a9c02024-01-12 20:14:5986 * Install `cargo vet` if it's not yet installed:
87 * `./tools/crates/run_cargo.py install --git https://github.com/mozilla/cargo-vet cargo-vet`
danakjaed1daf2024-01-05 17:44:3288 * We use `--git` to install cargo-vet from HEAD in order to use the `--cargo-arg` argument
89 which is not released yet.
danakj9535a9c02024-01-12 20:14:5990 * `./tools/crates/run_cargo.py -Zunstable-options -C third_party/rust/chromium_crates_io/ vet check --cargo-arg=-Zbindeps --no-registry-suggestions`
danakjaed1daf2024-01-05 17:44:3291 * If `check` fails, then there are missing audits, which need to be added to
92 `//third_party/rust/chromium_crates_io/supply-chain/audits.toml`.
93 * See [auditing_standards.md](https://github.com/google/rust-crate-audits/blob/main/auditing_standards.md)
94 for the criteria for audits.
95 * See [Cargo Vet documentation](https://mozilla.github.io/cargo-vet/recording-audits.html)
96 for how to record the audit in `audits.toml`.
97 * Some audits can be done by any engineer ("ub-risk-0" and "safe-to-run")
98 while others will require specialists from the Security team. These are
99 explained in the
100 [auditing_standards.md](https://github.com/google/rust-crate-audits/blob/main/auditing_standards.md).
101 * Audit updates in `audit.toml` should be part of the submitted CL so that
102 `cargo vet` will continue to pass after the CL lands.
1031. Upload the CL. If there is any `unsafe` usage then Security experts will need to
104 audit the "ub-risk" level. Mark any `unsafe` usage with `TODO` code review comments,
danakj0ec93d12023-11-17 16:12:23105 and include a link to it in the request for third-party and security review.
106
107### Cargo features
danakjbb4d0c772023-10-13 13:22:28108
109To enable a feature "spaceships" in the crate, change the entry in
danakj0ec93d12023-11-17 16:12:23110`//third_party/rust/chromium_crates_io/Cargo.toml` to include the feature:
danakjbb4d0c772023-10-13 13:22:28111```toml
112[dependencies]
113bar = { version = "3", features = [ "spaceships" ] }
114```
115
danakjf509caa2023-11-23 15:29:43116### Patching third-party crates
danakjbb4d0c772023-10-13 13:22:28117
118You may patch a crate in tree, but save any changes made into a diff file in
danakj98bec162023-11-21 14:55:02119a `//third_party/rust/chromium_crates_io/patches/` directory for the crate.
120The diff file should be generated by `git-format-patch` each new patch numbered
121consecutively so that they can be applied in order. For example, these files
122might exist if the "foo" crate was patched with a couple of changes:
danakjbb4d0c772023-10-13 13:22:28123
124```
danakj98bec162023-11-21 14:55:02125//third_party/rust/chromium_crates_io/patches/foo/patches/0001-Edit-the-Cargo-toml.diff
126//third_party/rust/chromium_crates_io/patches/foo/patches/0002-Other-changes.diff
danakjbb4d0c772023-10-13 13:22:28127```
128
Adrian Taylor138cb9f2023-11-08 18:41:54129The recommended procedure to create such patches is:
130
1311. Commit the plain new version of the crate to your local git branch
1322. Modify the crate as necessary
1333. Commit that modified version
1344. Use `git format-patch <unpatched version>` to generate the patch files
1355. Add the patch files in a new, third, commit
1366. Squash them, or rely on `git cl upload` doing so
137
danakjf509caa2023-11-23 15:29:43138#### Patching errors
139
140If `gnrt vendor` fails to apply a patch for a crate, it will cancel the download of that
141crate rather than leave it in a broken state. To recreate patches, first get a pristine
142copy of the crate by using the `--no-patches` argument:
143
1441. Download the crate without applying patches:
145 * `vpython3 ./tools/crates/run_gnrt.py vendor --no-patches=<CRATE_NAME>`
1462. Then recreate the patches as described in [Patching third-party crates](
147 #patching-third_party-crates).
148
149To verify the patches work, remove the vendored crate directory in
150`//third_party/rust/chromium_crates_io/vendor/`, named after the crate name
151and version. Then run the `vendor` action without `--no-patches` which will
152download the crate and apply the patches:
153 * `vpython3 ./tools/crates/run_gnrt.py vendor`
154
danakj98bec162023-11-21 14:55:02155## Security
danakjbb4d0c772023-10-13 13:22:28156
danakj98bec162023-11-21 14:55:02157If a shipping library needs security review (has any `unsafe`), and the review
158finds it's not satisfying the [rule of 2](../docs/security/rule-of-2.md), then
159move it to the `"sandbox"` group in `//third_party/rust/chromium_crates_io/gnrt_config.toml`
160to make it clear it can't be used in a privileged process:
161```
162[crate.foo]
163group = "sandbox"
164```
165
166If a transitive dependency moves from `"safe"` to `"sandbox"` and causes
167a dependency chain across the groups, it will break the `gnrt vendor` step.
168You will need to fix the new crate so that it's deemed safe in unsafe review,
169or move the other dependent crates out of `"safe"` as well by setting their
170group in `gnrt_config.toml`.
171
172# Updating existing third-party crates
173
174To update crates to their latest minor versions:
1751. Change directory to the root `src/` dir of Chromium.
Dominik Röttschesa07a5532024-01-24 19:16:231761. Update the versions in `//third_party/rust/chromium_crates_io/Cargo.toml`.
danakj98bec162023-11-21 14:55:02177 * `vpython3 ./tools/crates/run_gnrt.py update`
178 * Or, directly through (nightly) cargo:
179 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt update`
1801. Download any updated crate's files:
181 * `./tools/crates/run_gnrt.py vendor`
Dominik Röttschesa07a5532024-01-24 19:16:23182 * If you want to restrict the update to certain crates, add the crate names
183 as arguments to `vendor`, like: `./tools/crates/run_gnrt.py vendor
184 <crate-name>`
danakj98bec162023-11-21 14:55:02185 * Or, directly through (nightly) cargo:
186 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor`
Lukasz Anforowicz8452bd8d2023-11-28 23:31:551871. Add the downloaded files to git:
danakj98bec162023-11-21 14:55:02188 * `git add -f third_party/rust/chromium_crates_io/vendor`
189 * The `-f` is important, as files may be skipped otherwise from a
190 `.gitignore` inside the crate.
1911. If a crate in `//third_party/rust/chromium_crates_io/patches` was updated
192 as part of vendoring, then reapply patches to it:
193 * Go to the `//third_party/rust/chromium_crates_io` directory.
194 * `./apply_patches.sh` (this currently requires linux).
1951. Generate the `BUILD.gn` files
196 * `vpython3 ./tools/crates/run_gnrt.py gen`
197 * Or, directly through (nightly) cargo:
198 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`
Lukasz Anforowicz8452bd8d2023-11-28 23:31:551991. Add the generated files to git:
200 * `git add -f third_party/rust`
danakjbb4d0c772023-10-13 13:22:28201
202### Directory structure for third-party crates
203
204The directory structure for a crate "foo" version 3.4.2 is:
205```
206//third_party/
207 rust/
danakj98bec162023-11-21 14:55:02208 foo/ (for the "foo" crate)
Lukasz Anforowicz8452bd8d2023-11-28 23:31:55209 v3/ (version 3.4.2 maps to the v3 epoch)
danakjbb4d0c772023-10-13 13:22:28210 BUILD.gn (generated by gnrt gen)
danakj98bec162023-11-21 14:55:02211 README.chromium (generated by gnrt vendor)
Lukasz Anforowicz8452bd8d2023-11-28 23:31:55212 chromium_crates_io/
213 vendor/
214 foo-3.4.2 (crate sources downloaded from crates.io)
danakj98bec162023-11-21 14:55:02215 patches/
Lukasz Anforowicz8452bd8d2023-11-28 23:31:55216 foo/ (patches for the "foo" crate)
danakjbb4d0c772023-10-13 13:22:28217 0001-Edit-the-Cargo-toml.diff
218 0002-Other-changes.diff
Lukasz Anforowicz8452bd8d2023-11-28 23:31:55219 Cargo.toml
220 Cargo.lock
221 gnrt_config.toml
danakjbb4d0c772023-10-13 13:22:28222```
223
danakj6e25f742022-12-01 21:47:42224## Writing a wrapper for binding generation
225
226Most Rust libraries will need a more C++-friendly API written on top of them in
danakjbb4d0c772023-10-13 13:22:28227order to generate C++ bindings to them. The wrapper library can be placed
228in `//third_party/rust/<cratename>/<epoch>/wrapper` or at another single place
229that all C++ goes through to access the library. The [CXX](https://cxx.rs) is
230used to generate bindings between C++ and Rust.
danakj6e25f742022-12-01 21:47:42231
232See
danakjbb4d0c772023-10-13 13:22:28233[`//third_party/rust/serde_json_lenient/v0_1/wrapper/`](
234https://source.chromium.org/chromium/chromium/src/+/main:third_party/rust/serde_json_lenient/v0_1/wrapper/)
235and
236[`//components/qr_code_generator`](
237https://source.chromium.org/chromium/chromium/src/+/main:components/qr_code_generator/;l=1;drc=b185db5d502d4995627e09d62c6934590031a5f2)
238for examples.
danakj6e25f742022-12-01 21:47:42239
danakjbb4d0c772023-10-13 13:22:28240Rust libraries should use the
241[`rust_static_library`](
242https://source.chromium.org/chromium/chromium/src/+/main:build/rust/rust_static_library.gni)
243GN template (not the built-in `rust_library`) to integrate properly into the
244mixed-language Chromium build and get the correct compiler options applied to
245them.
danakj6e25f742022-12-01 21:47:42246
danakjbb4d0c772023-10-13 13:22:28247The [CXX](https://cxx.rs) tool is used for generating C++ bindings to Rust
248code. Since it requires explicit declarations in Rust, an wrapper shim around a
249pure Rust library is needed. Add these Rust shims that contain the CXX
250`bridge` macro to the `cxx_bindings` GN variable in the `rust_static_library`
251to have CXX generate a C++ header for that file. To include the C++ header
252file, rooted in the `gen` output directory, use
danakj6e25f742022-12-01 21:47:42253```
danakjbb4d0c772023-10-13 13:22:28254#include "the/path/to/the/rust/file.rs.h"
danakj6e25f742022-12-01 21:47:42255```
256
danakj6e25f742022-12-01 21:47:42257# Using VSCode
258
2591. Ensure you're using the `rust-analyzer` extension for VSCode, rather than
260 earlier forms of Rust support.
danakjbb4d0c772023-10-13 13:22:282612. Run `gn` with the `--export-rust-project` flag, such as:
262 `gn gen out/Release --export-rust-project`.
danakj6e25f742022-12-01 21:47:422633. `ln -s out/Release/rust-project.json rust-project.json`
2644. When you run VSCode, or any other IDE that uses
265 [rust-analyzer](https://rust-analyzer.github.io/) it should detect the
266 `rust-project.json` and use this to give you rich browsing, autocompletion,
267 type annotations etc. for all the Rust within the Chromium codebase.
danakjf3d7f372023-12-07 18:17:122685. Point rust-analyzer to the rust toolchain in Chromium. Otherwise you will
269 need to install Rustc in your system, and Chromium uses the nightly
270 compiler, so you would need that to match. Add the following to
271 `.vscode/settings.json` in the Chromium checkout:
272 ```
273 {
274 // The rest of the settings...
275
276 "rust-analyzer.cargo.extraEnv": {
277 "PATH": "../../third_party/rust-toolchain/bin:$PATH",
278 }
279 }
280 ```
281 This assumes you are working with an output directory like `out/Debug` which
282 has two levels; adjust the number of `..` in the path according to your own
283 setup.
Adrian Taylorc5fbb572023-11-21 14:25:42284
285# Using cargo
286
287If you are building a throwaway or experimental tool, you might like to use pure
288`cargo` tooling rather than `gn` and `ninja`. Even then, you may choose
289to restrict yourself to the toolchain and crates that are already approved for
290use in Chromium.
291
292Here's how.
293
294```
295export PATH_TO_CHROMIUM_SRC=~/chromium/src
296mkdir my-rust-tool
297cd my-rust-tool
298mkdir .cargo
299cat <<END > .cargo/config.toml
300[source.crates-io]
301replace-with = "vendored-sources"
302
303[source.vendored-sources]
304directory = "$PATH_TO_CHROMIUM_SRC/third_party/rust/chromium_crates_io/vendor"
305END
306$PATH_TO_CHROMIUM_SRC/third_party/rust-toolchain/bin/cargo init --offline
307$PATH_TO_CHROMIUM_SRC/third_party/rust-toolchain/bin/cargo run --offline
308```
309
310Most `cargo` tooling works well with this setup; one exception is `cargo add`,
311but you can still add dependencies manually to your `Cargo.toml`:
312
313```
314[dependencies]
315log = "0.4"
316```