blob: 70f3f3caeac98c85ada849a9612fab2c85a0ba76 [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
danakj0ec93d12023-11-17 16:12:2350To use a third-party crate "bar" version 3 from first party code:
danakj98bec162023-11-21 14:55:02511. Change directory to the root `src/` dir of Chromium.
521. Add the crate to `//third_party/rust/chromium_crates_io/Cargo.toml`:
53 * `vpython3 ./tools/crates/run_gnrt.py add foo` to add the latest version of `foo`.
54 * `vpython3 ./tools/crates/run_gnrt.py add [email protected]` to add a specific version of `foo`.
55 * Or, directly through (nightly) cargo:
56 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt add foo`
57 * Or, edit the Cargo.toml by hand, finding the version you want from [crates.io](https://crates.io).
581. Download the crate's files:
59 * `./tools/crates/run_gnrt.py vendor` to download the new crate.
60 * Or, directly through (nightly) cargo:
danakj0ec93d12023-11-17 16:12:2361 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor`
danakj98bec162023-11-21 14:55:02621. Add the new files to git:
63 * `git add -f third_party/rust/chromium_crates_io/vendor`
64 * The `-f` is important, as files may be skipped otherwise from a
65 `.gitignore` inside the crate.
661. If a crate in `//third_party/rust/chromium_crates_io/patches` was updated
danakj0ec93d12023-11-17 16:12:2367 as part of vendoring, then reapply patches to it:
danakj98bec162023-11-21 14:55:0268 * Go to the `//third_party/rust/chromium_crates_io` directory.
danakj0ec93d12023-11-17 16:12:2369 * `./apply_patches.sh` (this currently requires linux).
danakj98bec162023-11-21 14:55:02701. (optional) If the crate is only to be used by tests and tooling, then
71 specify the `"test"` group in `//third_party/rust/chromium_crates_io/gnrt_config.toml`:
72 ```
73 [crate.foo]
74 group = "test"
75 ```
761. Generate the `BUILD.gn` file for the new crate:
77 * `vpython3 ./tools/crates/run_gnrt.py gen`
78 * Or, directly through (nightly) cargo:
79 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`
801. Upload the CL, mark any `unsafe` usage with `TODO` code review comments,
danakj0ec93d12023-11-17 16:12:2381 and include a link to it in the request for third-party and security review.
82
83### Cargo features
danakjbb4d0c772023-10-13 13:22:2884
85To enable a feature "spaceships" in the crate, change the entry in
danakj0ec93d12023-11-17 16:12:2386`//third_party/rust/chromium_crates_io/Cargo.toml` to include the feature:
danakjbb4d0c772023-10-13 13:22:2887```toml
88[dependencies]
89bar = { version = "3", features = [ "spaceships" ] }
90```
91
danakjbb4d0c772023-10-13 13:22:2892### Patching third-party crates.
93
94You may patch a crate in tree, but save any changes made into a diff file in
danakj98bec162023-11-21 14:55:0295a `//third_party/rust/chromium_crates_io/patches/` directory for the crate.
96The diff file should be generated by `git-format-patch` each new patch numbered
97consecutively so that they can be applied in order. For example, these files
98might exist if the "foo" crate was patched with a couple of changes:
danakjbb4d0c772023-10-13 13:22:2899
100```
danakj98bec162023-11-21 14:55:02101//third_party/rust/chromium_crates_io/patches/foo/patches/0001-Edit-the-Cargo-toml.diff
102//third_party/rust/chromium_crates_io/patches/foo/patches/0002-Other-changes.diff
danakjbb4d0c772023-10-13 13:22:28103```
104
Adrian Taylor138cb9f2023-11-08 18:41:54105The recommended procedure to create such patches is:
106
1071. Commit the plain new version of the crate to your local git branch
1082. Modify the crate as necessary
1093. Commit that modified version
1104. Use `git format-patch <unpatched version>` to generate the patch files
1115. Add the patch files in a new, third, commit
1126. Squash them, or rely on `git cl upload` doing so
113
danakj98bec162023-11-21 14:55:02114## Security
danakjbb4d0c772023-10-13 13:22:28115
danakj98bec162023-11-21 14:55:02116If a shipping library needs security review (has any `unsafe`), and the review
117finds it's not satisfying the [rule of 2](../docs/security/rule-of-2.md), then
118move it to the `"sandbox"` group in `//third_party/rust/chromium_crates_io/gnrt_config.toml`
119to make it clear it can't be used in a privileged process:
120```
121[crate.foo]
122group = "sandbox"
123```
124
125If a transitive dependency moves from `"safe"` to `"sandbox"` and causes
126a dependency chain across the groups, it will break the `gnrt vendor` step.
127You will need to fix the new crate so that it's deemed safe in unsafe review,
128or move the other dependent crates out of `"safe"` as well by setting their
129group in `gnrt_config.toml`.
130
131# Updating existing third-party crates
132
133To update crates to their latest minor versions:
1341. Change directory to the root `src/` dir of Chromium.
1351. Update the versions in `//third_party/rust/chromium_crates_io/Cargo.lock`.
136 * `vpython3 ./tools/crates/run_gnrt.py update`
137 * Or, directly through (nightly) cargo:
138 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt update`
1391. Download any updated crate's files:
140 * `./tools/crates/run_gnrt.py vendor`
141 * Or, directly through (nightly) cargo:
142 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor`
1431. Add the new files to git:
144 * `git add -f third_party/rust/chromium_crates_io/vendor`
145 * The `-f` is important, as files may be skipped otherwise from a
146 `.gitignore` inside the crate.
1471. If a crate in `//third_party/rust/chromium_crates_io/patches` was updated
148 as part of vendoring, then reapply patches to it:
149 * Go to the `//third_party/rust/chromium_crates_io` directory.
150 * `./apply_patches.sh` (this currently requires linux).
1511. Generate the `BUILD.gn` files
152 * `vpython3 ./tools/crates/run_gnrt.py gen`
153 * Or, directly through (nightly) cargo:
154 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`
danakjbb4d0c772023-10-13 13:22:28155
156### Directory structure for third-party crates
157
158The directory structure for a crate "foo" version 3.4.2 is:
159```
160//third_party/
161 rust/
danakj98bec162023-11-21 14:55:02162 foo/ (for the "foo" crate)
danakjbb4d0c772023-10-13 13:22:28163 v3/
164 BUILD.gn (generated by gnrt gen)
danakj98bec162023-11-21 14:55:02165 README.chromium (generated by gnrt vendor)
166 chromium_crates_io/ (crate root)
167 patches/
168 foo/ (for the "foo" crate)
danakjbb4d0c772023-10-13 13:22:28169 0001-Edit-the-Cargo-toml.diff
170 0002-Other-changes.diff
danakj98bec162023-11-21 14:55:02171 Cargo.toml
172 Cargo.lock
173 gnrt_config.toml
174 vendor/
175 ...crate sources...
danakjbb4d0c772023-10-13 13:22:28176```
177
danakj6e25f742022-12-01 21:47:42178## Writing a wrapper for binding generation
179
180Most Rust libraries will need a more C++-friendly API written on top of them in
danakjbb4d0c772023-10-13 13:22:28181order to generate C++ bindings to them. The wrapper library can be placed
182in `//third_party/rust/<cratename>/<epoch>/wrapper` or at another single place
183that all C++ goes through to access the library. The [CXX](https://cxx.rs) is
184used to generate bindings between C++ and Rust.
danakj6e25f742022-12-01 21:47:42185
186See
danakjbb4d0c772023-10-13 13:22:28187[`//third_party/rust/serde_json_lenient/v0_1/wrapper/`](
188https://source.chromium.org/chromium/chromium/src/+/main:third_party/rust/serde_json_lenient/v0_1/wrapper/)
189and
190[`//components/qr_code_generator`](
191https://source.chromium.org/chromium/chromium/src/+/main:components/qr_code_generator/;l=1;drc=b185db5d502d4995627e09d62c6934590031a5f2)
192for examples.
danakj6e25f742022-12-01 21:47:42193
danakjbb4d0c772023-10-13 13:22:28194Rust libraries should use the
195[`rust_static_library`](
196https://source.chromium.org/chromium/chromium/src/+/main:build/rust/rust_static_library.gni)
197GN template (not the built-in `rust_library`) to integrate properly into the
198mixed-language Chromium build and get the correct compiler options applied to
199them.
danakj6e25f742022-12-01 21:47:42200
danakjbb4d0c772023-10-13 13:22:28201The [CXX](https://cxx.rs) tool is used for generating C++ bindings to Rust
202code. Since it requires explicit declarations in Rust, an wrapper shim around a
203pure Rust library is needed. Add these Rust shims that contain the CXX
204`bridge` macro to the `cxx_bindings` GN variable in the `rust_static_library`
205to have CXX generate a C++ header for that file. To include the C++ header
206file, rooted in the `gen` output directory, use
danakj6e25f742022-12-01 21:47:42207```
danakjbb4d0c772023-10-13 13:22:28208#include "the/path/to/the/rust/file.rs.h"
danakj6e25f742022-12-01 21:47:42209```
210
danakj6e25f742022-12-01 21:47:42211# Using VSCode
212
2131. Ensure you're using the `rust-analyzer` extension for VSCode, rather than
214 earlier forms of Rust support.
danakjbb4d0c772023-10-13 13:22:282152. Run `gn` with the `--export-rust-project` flag, such as:
216 `gn gen out/Release --export-rust-project`.
danakj6e25f742022-12-01 21:47:422173. `ln -s out/Release/rust-project.json rust-project.json`
2184. When you run VSCode, or any other IDE that uses
219 [rust-analyzer](https://rust-analyzer.github.io/) it should detect the
220 `rust-project.json` and use this to give you rich browsing, autocompletion,
221 type annotations etc. for all the Rust within the Chromium codebase.
Adrian Taylorc5fbb572023-11-21 14:25:42222
223# Using cargo
224
225If you are building a throwaway or experimental tool, you might like to use pure
226`cargo` tooling rather than `gn` and `ninja`. Even then, you may choose
227to restrict yourself to the toolchain and crates that are already approved for
228use in Chromium.
229
230Here's how.
231
232```
233export PATH_TO_CHROMIUM_SRC=~/chromium/src
234mkdir my-rust-tool
235cd my-rust-tool
236mkdir .cargo
237cat <<END > .cargo/config.toml
238[source.crates-io]
239replace-with = "vendored-sources"
240
241[source.vendored-sources]
242directory = "$PATH_TO_CHROMIUM_SRC/third_party/rust/chromium_crates_io/vendor"
243END
244$PATH_TO_CHROMIUM_SRC/third_party/rust-toolchain/bin/cargo init --offline
245$PATH_TO_CHROMIUM_SRC/third_party/rust-toolchain/bin/cargo run --offline
246```
247
248Most `cargo` tooling works well with this setup; one exception is `cargo add`,
249but you can still add dependencies manually to your `Cargo.toml`:
250
251```
252[dependencies]
253log = "0.4"
254```