blob: cf10de51ea429d2add0970ad22900ee41598ad67 [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
David Adriand8918692024-12-12 22:02:5022Rust can be used anywhere in the Chromium repository (not just `//third_party`)
23subject to [current interop capabilities][interop-rust-doc], however it is
24currently subject to a internal approval and FYI process. Googlers can view
25go/chrome-rust for details. New usages of Rust are documented at
26[`[email protected]`](https://groups.google.com/a/chromium.org/g/rust-fyi).
danakj6e25f742022-12-01 21:47:4227
28For questions or help, reach out to `[email protected]` or `#rust` on the
29[Chromium Slack](https://www.chromium.org/developers/slack/).
30
danakj6e25f742022-12-01 21:47:4231If you use VSCode, we have [additional advice below](#using-vscode).
32
danakjbb4d0c772023-10-13 13:22:2833# Adding a third-party Rust library
danakj6e25f742022-12-01 21:47:4234
danakjbb4d0c772023-10-13 13:22:2835Third-party libraries are pulled from [crates.io](https://crates.io), but
36Chromium does not use Cargo as a build system.
danakj6e25f742022-12-01 21:47:4237
38## Third-party review
39
danakj6e25f742022-12-01 21:47:4240All third-party crates need to go through third-party review. See
41[//docs/adding_to_third_party.md](adding_to_third_party.md) for instructions on
42how to have a library reviewed.
43
danakjbb4d0c772023-10-13 13:22:2844## Importing a crate from crates.io
45
danakj0ec93d12023-11-17 16:12:2346The `//third_party/rust/chromium_crates_io/Cargo.toml` file defines the set of crates
danakjbb4d0c772023-10-13 13:22:2847depended on from first-party code. Any transitive dependencies will be found
danakj0ec93d12023-11-17 16:12:2348from those listed there. The file is a [standard `Cargo.toml` file](
49https://doc.rust-lang.org/cargo/reference/manifest.html), though the crate
50itself is never built, it is only used to collect dependencies through the
51`[dependencies]` section.
danakjbb4d0c772023-10-13 13:22:2852
danakj0ec93d12023-11-17 16:12:2353To use a third-party crate "bar" version 3 from first party code:
danakj98bec162023-11-21 14:55:02541. Change directory to the root `src/` dir of Chromium.
551. Add the crate to `//third_party/rust/chromium_crates_io/Cargo.toml`:
56 * `vpython3 ./tools/crates/run_gnrt.py add foo` to add the latest version of `foo`.
57 * `vpython3 ./tools/crates/run_gnrt.py add [email protected]` to add a specific version of `foo`.
58 * Or, directly through (nightly) cargo:
59 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt add foo`
60 * Or, edit the Cargo.toml by hand, finding the version you want from [crates.io](https://crates.io).
611. Download the crate's files:
62 * `./tools/crates/run_gnrt.py vendor` to download the new crate.
63 * Or, directly through (nightly) cargo:
danakj0ec93d12023-11-17 16:12:2364 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor`
danakjf509caa2023-11-23 15:29:4365 * This will also apply any patches in `//third_party/rust/chromium_crates_io/patches`
66 for the crates. If a patch can not apply, the crate's download will be cancelled and
67 an error will be printed. See [patching errors](#patching-errors) below for how to resolve
68 this.
danakj98bec162023-11-21 14:55:02691. (optional) If the crate is only to be used by tests and tooling, then
70 specify the `"test"` group in `//third_party/rust/chromium_crates_io/gnrt_config.toml`:
71 ```
72 [crate.foo]
73 group = "test"
74 ```
751. Generate the `BUILD.gn` file for the new crate:
76 * `vpython3 ./tools/crates/run_gnrt.py gen`
77 * Or, directly through (nightly) cargo:
78 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`
Lukasz Anforowicz652bf4a2024-03-20 16:48:29791. Verify if all new dependencies are already audited by running `cargo vet`
Lukasz Anforowiczdf3d5af2024-03-20 18:21:1680 See [`rust-unsafe.md#cargo-vet-policy`](rust-unsafe.md#cargo-vet-policy) for
Lukasz Anforowicz652bf4a2024-03-20 16:48:2981 more details. This boils down to:
Lukasz Anforowicz11c34872024-01-25 17:15:4682 * `./tools/crates/run_cargo_vet.py check`
danakjaed1daf2024-01-05 17:44:3283 * If `check` fails, then there are missing audits, which need to be added to
84 `//third_party/rust/chromium_crates_io/supply-chain/audits.toml`.
Lukasz Anforowicz057876d2024-06-05 19:07:58851. Add the new files to git:
86 * `git add -f third_party/rust/chromium_crates_io/vendor`.
87 (The `-f` is important, as files may be skipped otherwise from a
88 `.gitignore` inside the crate.)
89 * `git add third_party/rust`
danakjaed1daf2024-01-05 17:44:32901. Upload the CL. If there is any `unsafe` usage then Security experts will need to
Lukasz Anforowicz652bf4a2024-03-20 16:48:2991 audit the "ub-risk" level. See
Lukasz Anforowiczdf3d5af2024-03-20 18:21:1692 [`rust-unsafe.md#code-review-policy`](rust-unsafe.md#code-review-policy) for
Lukasz Anforowicz652bf4a2024-03-20 16:48:2993 more details.
danakj0ec93d12023-11-17 16:12:2394
95### Cargo features
danakjbb4d0c772023-10-13 13:22:2896
97To enable a feature "spaceships" in the crate, change the entry in
danakj0ec93d12023-11-17 16:12:2398`//third_party/rust/chromium_crates_io/Cargo.toml` to include the feature:
danakjbb4d0c772023-10-13 13:22:2899```toml
100[dependencies]
101bar = { version = "3", features = [ "spaceships" ] }
102```
103
danakjf509caa2023-11-23 15:29:43104### Patching third-party crates
danakjbb4d0c772023-10-13 13:22:28105
106You may patch a crate in tree, but save any changes made into a diff file in
danakj98bec162023-11-21 14:55:02107a `//third_party/rust/chromium_crates_io/patches/` directory for the crate.
108The diff file should be generated by `git-format-patch` each new patch numbered
109consecutively so that they can be applied in order. For example, these files
110might exist if the "foo" crate was patched with a couple of changes:
danakjbb4d0c772023-10-13 13:22:28111
112```
danakj98bec162023-11-21 14:55:02113//third_party/rust/chromium_crates_io/patches/foo/patches/0001-Edit-the-Cargo-toml.diff
114//third_party/rust/chromium_crates_io/patches/foo/patches/0002-Other-changes.diff
danakjbb4d0c772023-10-13 13:22:28115```
116
Adrian Taylor138cb9f2023-11-08 18:41:54117The recommended procedure to create such patches is:
118
1191. Commit the plain new version of the crate to your local git branch
1202. Modify the crate as necessary
1213. Commit that modified version
1224. Use `git format-patch <unpatched version>` to generate the patch files
1235. Add the patch files in a new, third, commit
1246. Squash them, or rely on `git cl upload` doing so
125
danakjf509caa2023-11-23 15:29:43126#### Patching errors
127
128If `gnrt vendor` fails to apply a patch for a crate, it will cancel the download of that
129crate rather than leave it in a broken state. To recreate patches, first get a pristine
130copy of the crate by using the `--no-patches` argument:
131
1321. Download the crate without applying patches:
133 * `vpython3 ./tools/crates/run_gnrt.py vendor --no-patches=<CRATE_NAME>`
1342. Then recreate the patches as described in [Patching third-party crates](
135 #patching-third_party-crates).
136
137To verify the patches work, remove the vendored crate directory in
138`//third_party/rust/chromium_crates_io/vendor/`, named after the crate name
139and version. Then run the `vendor` action without `--no-patches` which will
140download the crate and apply the patches:
141 * `vpython3 ./tools/crates/run_gnrt.py vendor`
142
danakj98bec162023-11-21 14:55:02143## Security
danakjbb4d0c772023-10-13 13:22:28144
danakj98bec162023-11-21 14:55:02145If a shipping library needs security review (has any `unsafe`), and the review
146finds it's not satisfying the [rule of 2](../docs/security/rule-of-2.md), then
147move it to the `"sandbox"` group in `//third_party/rust/chromium_crates_io/gnrt_config.toml`
148to make it clear it can't be used in a privileged process:
149```
150[crate.foo]
151group = "sandbox"
152```
153
154If a transitive dependency moves from `"safe"` to `"sandbox"` and causes
155a dependency chain across the groups, it will break the `gnrt vendor` step.
156You will need to fix the new crate so that it's deemed safe in unsafe review,
157or move the other dependent crates out of `"safe"` as well by setting their
158group in `gnrt_config.toml`.
159
160# Updating existing third-party crates
161
Lukasz Anforowicz85528a62024-03-20 19:12:53162Third-party crates will get updated semi-automatically through the process
163described in
164[`../tools/crates/create_update_cl.md`](../tools/crates/create_update_cl.md).
165If you nevertheless need to manually update a crate to its latest minor
166version, then follow the steps below:
167
danakj98bec162023-11-21 14:55:021681. Change directory to the root `src/` dir of Chromium.
Dominik Röttschesa07a5532024-01-24 19:16:231691. Update the versions in `//third_party/rust/chromium_crates_io/Cargo.toml`.
Lukasz Anforowicz85528a62024-03-20 19:12:53170 * `vpython3 ./tools/crates/run_gnrt.py update <crate name>`
danakj98bec162023-11-21 14:55:02171 * Or, directly through (nightly) cargo:
Lukasz Anforowicz85528a62024-03-20 19:12:53172 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt update <crate name>`
danakj98bec162023-11-21 14:55:021731. Download any updated crate's files:
174 * `./tools/crates/run_gnrt.py vendor`
Dominik Röttschesa07a5532024-01-24 19:16:23175 * If you want to restrict the update to certain crates, add the crate names
176 as arguments to `vendor`, like: `./tools/crates/run_gnrt.py vendor
177 <crate-name>`
danakj98bec162023-11-21 14:55:02178 * Or, directly through (nightly) cargo:
179 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor`
Lukasz Anforowicz8452bd8d2023-11-28 23:31:551801. Add the downloaded files to git:
danakj98bec162023-11-21 14:55:02181 * `git add -f third_party/rust/chromium_crates_io/vendor`
182 * The `-f` is important, as files may be skipped otherwise from a
183 `.gitignore` inside the crate.
danakj98bec162023-11-21 14:55:021841. Generate the `BUILD.gn` files
185 * `vpython3 ./tools/crates/run_gnrt.py gen`
186 * Or, directly through (nightly) cargo:
187 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`
Lukasz Anforowicz8452bd8d2023-11-28 23:31:551881. Add the generated files to git:
189 * `git add -f third_party/rust`
danakjbb4d0c772023-10-13 13:22:28190
191### Directory structure for third-party crates
192
193The directory structure for a crate "foo" version 3.4.2 is:
194```
195//third_party/
196 rust/
danakj98bec162023-11-21 14:55:02197 foo/ (for the "foo" crate)
Lukasz Anforowicz8452bd8d2023-11-28 23:31:55198 v3/ (version 3.4.2 maps to the v3 epoch)
danakjbb4d0c772023-10-13 13:22:28199 BUILD.gn (generated by gnrt gen)
danakj98bec162023-11-21 14:55:02200 README.chromium (generated by gnrt vendor)
Lukasz Anforowicz8452bd8d2023-11-28 23:31:55201 chromium_crates_io/
202 vendor/
203 foo-3.4.2 (crate sources downloaded from crates.io)
danakj98bec162023-11-21 14:55:02204 patches/
Lukasz Anforowicz8452bd8d2023-11-28 23:31:55205 foo/ (patches for the "foo" crate)
danakjbb4d0c772023-10-13 13:22:28206 0001-Edit-the-Cargo-toml.diff
207 0002-Other-changes.diff
Lukasz Anforowicz8452bd8d2023-11-28 23:31:55208 Cargo.toml
209 Cargo.lock
210 gnrt_config.toml
danakjbb4d0c772023-10-13 13:22:28211```
212
danakj6e25f742022-12-01 21:47:42213## Writing a wrapper for binding generation
214
215Most Rust libraries will need a more C++-friendly API written on top of them in
danakjbb4d0c772023-10-13 13:22:28216order to generate C++ bindings to them. The wrapper library can be placed
217in `//third_party/rust/<cratename>/<epoch>/wrapper` or at another single place
218that all C++ goes through to access the library. The [CXX](https://cxx.rs) is
219used to generate bindings between C++ and Rust.
danakj6e25f742022-12-01 21:47:42220
221See
danakjbb4d0c772023-10-13 13:22:28222[`//third_party/rust/serde_json_lenient/v0_1/wrapper/`](
223https://source.chromium.org/chromium/chromium/src/+/main:third_party/rust/serde_json_lenient/v0_1/wrapper/)
224and
225[`//components/qr_code_generator`](
226https://source.chromium.org/chromium/chromium/src/+/main:components/qr_code_generator/;l=1;drc=b185db5d502d4995627e09d62c6934590031a5f2)
227for examples.
danakj6e25f742022-12-01 21:47:42228
danakjbb4d0c772023-10-13 13:22:28229Rust libraries should use the
230[`rust_static_library`](
231https://source.chromium.org/chromium/chromium/src/+/main:build/rust/rust_static_library.gni)
232GN template (not the built-in `rust_library`) to integrate properly into the
233mixed-language Chromium build and get the correct compiler options applied to
234them.
danakj6e25f742022-12-01 21:47:42235
danakjbb4d0c772023-10-13 13:22:28236The [CXX](https://cxx.rs) tool is used for generating C++ bindings to Rust
237code. Since it requires explicit declarations in Rust, an wrapper shim around a
238pure Rust library is needed. Add these Rust shims that contain the CXX
239`bridge` macro to the `cxx_bindings` GN variable in the `rust_static_library`
240to have CXX generate a C++ header for that file. To include the C++ header
241file, rooted in the `gen` output directory, use
danakj6e25f742022-12-01 21:47:42242```
danakjbb4d0c772023-10-13 13:22:28243#include "the/path/to/the/rust/file.rs.h"
danakj6e25f742022-12-01 21:47:42244```
245
danakj3d037ff2024-11-07 19:31:41246# Logging
Adrian Taylor91eaa362024-02-09 14:17:03247
danakj3d037ff2024-11-07 19:31:41248Use the [log](https://docs.rs/log) crate's macros in place of base `LOG`
249macros from C++. They do the same things. The `debug!` macro maps to
250`DLOG(INFO)`, the `info!` macro maps to `LOG(INFO)`, and `warn!` and `error!`
251map to `LOG(WARNING)` and `LOG(ERROR)` respectively. The additional `trace!`
252macro maps to `DLOG(INFO)` (but there is [WIP to map it to `DVLOG(INFO)`](
253https://chromium-review.googlesource.com/c/chromium/src/+/5996820)).
254
255Note that the standard library also includes a helpful
256[`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro which writes
257everything about a variable to `stderr`.
258
259Logging may not yet work in component builds:
260[crbug.com/374023535](https://crbug.com/374023535).
261
262# Tracing
263
264TODO: [crbug.com/377915495](https://crbug.com/377915495).
265
266# Strings
267
268Prefer to use [`BString`](https://docs.rs/bstr/latest/bstr/struct.BString.html)
269and [`BStr`](https://docs.rs/bstr/latest/bstr/struct.BStr.html) to work with
270strings in first-party code instead of `std::String` and `str`. These types do
271not require the strings to be valid UTF-8, and avoid error handling or panic
272crashes when working with strings from C++ and/or from the web. Because the
273web is not UTF-8 encoded, many strings in Chromium are also not.
274
275In cross-language bindings, `&[u8]` can be used to represent a string until
276native support for `BStr` is available in our interop tooling. A `u8` slice
277can be converted to `BStr` or treated as a string with
278[`ByteSlice`](https://docs.rs/bstr/latest/bstr/trait.ByteSlice.html).
Adrian Taylor91eaa362024-02-09 14:17:03279
danakj6e25f742022-12-01 21:47:42280# Using VSCode
281
2821. Ensure you're using the `rust-analyzer` extension for VSCode, rather than
283 earlier forms of Rust support.
danakjbb4d0c772023-10-13 13:22:282842. Run `gn` with the `--export-rust-project` flag, such as:
285 `gn gen out/Release --export-rust-project`.
danakj6e25f742022-12-01 21:47:422863. `ln -s out/Release/rust-project.json rust-project.json`
2874. When you run VSCode, or any other IDE that uses
288 [rust-analyzer](https://rust-analyzer.github.io/) it should detect the
289 `rust-project.json` and use this to give you rich browsing, autocompletion,
290 type annotations etc. for all the Rust within the Chromium codebase.
danakjf3d7f372023-12-07 18:17:122915. Point rust-analyzer to the rust toolchain in Chromium. Otherwise you will
292 need to install Rustc in your system, and Chromium uses the nightly
293 compiler, so you would need that to match. Add the following to
294 `.vscode/settings.json` in the Chromium checkout:
295 ```
296 {
297 // The rest of the settings...
298
299 "rust-analyzer.cargo.extraEnv": {
300 "PATH": "../../third_party/rust-toolchain/bin:$PATH",
301 }
302 }
303 ```
304 This assumes you are working with an output directory like `out/Debug` which
305 has two levels; adjust the number of `..` in the path according to your own
306 setup.
Adrian Taylorc5fbb572023-11-21 14:25:42307
308# Using cargo
309
310If you are building a throwaway or experimental tool, you might like to use pure
311`cargo` tooling rather than `gn` and `ninja`. Even then, you may choose
312to restrict yourself to the toolchain and crates that are already approved for
313use in Chromium.
314
315Here's how.
316
317```
318export PATH_TO_CHROMIUM_SRC=~/chromium/src
319mkdir my-rust-tool
320cd my-rust-tool
321mkdir .cargo
322cat <<END > .cargo/config.toml
323[source.crates-io]
324replace-with = "vendored-sources"
325
326[source.vendored-sources]
327directory = "$PATH_TO_CHROMIUM_SRC/third_party/rust/chromium_crates_io/vendor"
328END
329$PATH_TO_CHROMIUM_SRC/third_party/rust-toolchain/bin/cargo init --offline
330$PATH_TO_CHROMIUM_SRC/third_party/rust-toolchain/bin/cargo run --offline
331```
332
333Most `cargo` tooling works well with this setup; one exception is `cargo add`,
334but you can still add dependencies manually to your `Cargo.toml`:
335
336```
337[dependencies]
338log = "0.4"
339```
David Adriand8918692024-12-12 22:02:50340
341[interop-rust-doc]: https://docs.google.com/document/d/1kvgaVMB_isELyDQ4nbMJYWrqrmL3UZI4tDxnyxy9RTE/edit?tab=t.0#heading=h.fpqr6hf3c3j0