blob: 41033d4e630e77dd90e1f0e97a73ceb2151ef531 [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 `rust-dev@chromium.org` 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:
511. Add the crate to `//third_party/rust/chromium_crates_io/Cargo.toml` in
52 `[dependencies]`:
53 ```toml
54 [dependencies]
55 bar = "3"
56 ```
572. Go to the `//third_party/rust/chromium_crates_io` directory and run:
58 * `vpython3 ./tools/crates/run_gnrt.py vendor` to download the new crate.
59 * Or, directly through cargo:
60 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor`
613. If a crate in `//third_party/rust/chromium_crates_io/patches` was updated
62 as part of vendoring, then reapply patches to it:
63 * `./apply_patches.sh` (this currently requires linux).
644. Generate the `BUILD.gn` file for the new crate (see below).
655. Create a `README.chromium` file next to the `BUILD.gn` file in
66 `//third_party/rust/crate_name/version/`.
676. Upload the CL, mark any `unsafe` usage with `TODO` code review comments,
68 and include a link to it in the request for third-party and security review.
69
70### Cargo features
danakjbb4d0c772023-10-13 13:22:2871
72To enable a feature "spaceships" in the crate, change the entry in
danakj0ec93d12023-11-17 16:12:2373`//third_party/rust/chromium_crates_io/Cargo.toml` to include the feature:
danakjbb4d0c772023-10-13 13:22:2874```toml
75[dependencies]
76bar = { version = "3", features = [ "spaceships" ] }
77```
78
79### Generating `BUILD.gn` files for third-party crates
80
81To generate `BUILD.gn` files for all third-party crates, and find missing
82transitive dependencies to download, use the `gnrt` tool:
83
841. Change directory to the root `src/` dir of Chromium.
851. Run `vpython3 ./tools/crates/run_gnrt.py gen` to build and run gnrt with the `gen` action.
86
87Or, to directly build and run gnrt with the system Rust toolchain:
88
891. Change directory to the root `src/` dir of Chromium.
901. Build and run `gnrt gen`:
91 `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`.
92
93This will generate a `BUILD.gn` file for each third-party crate. The `BUILD.gn`
94file changes will be visible in `git status` and can be added with `git add`.
95
96### Downloading missing third-party crates
97
98To download crate "foo", at version 4.2.3:
991. Change directory to the root src/ dir of Chromium.
1001. Run `gnrt` with the `download` action. e.g.
101 `vpython3 ./tools/crates/run_gnrt.py download --security-critical=yes --shipped=yes foo 4.2.3`
102
103This will download the crate and unpack it into
104`//third_party/rust/foo/v4/crate`. The entire `v4` directory, which includes the
105`crate` subdirectory as well as a generated `README.chromium` file, should be
106added to the repository with `git add third_party/rust/foo/v4`.
107
108Once all the crates are downloaded and `gnrt gen` completes, a CL can be
109uploaded to go through third-party review.
110
111### Patching third-party crates.
112
113You may patch a crate in tree, but save any changes made into a diff file in
114a `patches/` directory for the crate. The diff file should be generated by
115`git-format-patch` each new patch numbered consecutively so that they can be
116applied in order. For example, these files might exist if the "foo" crate was
117patched with a couple of changes:
118
119```
120//third_party/rust/foo/v4/patches/0001-Edit-the-Cargo-toml.diff
121//third_party/rust/foo/v4/patches/0002-Other-changes.diff
122```
123
Adrian Taylor138cb9f2023-11-08 18:41:54124The recommended procedure to create such patches is:
125
1261. Commit the plain new version of the crate to your local git branch
1272. Modify the crate as necessary
1283. Commit that modified version
1294. Use `git format-patch <unpatched version>` to generate the patch files
1305. Add the patch files in a new, third, commit
1316. Squash them, or rely on `git cl upload` doing so
132
danakjbb4d0c772023-10-13 13:22:28133### Updating existing third-party crates
134
135To update a crate "foo" to the latest version you must just re-import it at this
136time. To update from version "1.2.0" to "1.3.2":
1371. Remove the `//third_party/rust/foo/v1/crate` directory, which contains the
138 upstream code.
1391. Re-download the crate at the new version with `out/gnrt/release/gnrt download
140 foo 1.3.2`.
1411. If there are any, re-apply local patches with
142 `for i in $(find third_party/rust/foo/v1/patches/*); do patch -p1 < $i; done`
1431. Run `vpython3 ./tools/crates/run_gnrt.py gen` to re-generate all third-party
144 `BUILD.gn` files.
1451. Build `all_rust` to verify things are working.
146
147### Directory structure for third-party crates
148
149The directory structure for a crate "foo" version 3.4.2 is:
150```
151//third_party/
152 rust/
153 foo/
154 v3/
155 BUILD.gn (generated by gnrt gen)
156 README.chromium (generated by gnrt download)
157 crate/
158 Cargo.toml
159 src/
160 ...etc...
161 patches/
162 0001-Edit-the-Cargo-toml.diff
163 0002-Other-changes.diff
164```
165
danakj6e25f742022-12-01 21:47:42166## Writing a wrapper for binding generation
167
168Most Rust libraries will need a more C++-friendly API written on top of them in
danakjbb4d0c772023-10-13 13:22:28169order to generate C++ bindings to them. The wrapper library can be placed
170in `//third_party/rust/<cratename>/<epoch>/wrapper` or at another single place
171that all C++ goes through to access the library. The [CXX](https://cxx.rs) is
172used to generate bindings between C++ and Rust.
danakj6e25f742022-12-01 21:47:42173
174See
danakjbb4d0c772023-10-13 13:22:28175[`//third_party/rust/serde_json_lenient/v0_1/wrapper/`](
176https://source.chromium.org/chromium/chromium/src/+/main:third_party/rust/serde_json_lenient/v0_1/wrapper/)
177and
178[`//components/qr_code_generator`](
179https://source.chromium.org/chromium/chromium/src/+/main:components/qr_code_generator/;l=1;drc=b185db5d502d4995627e09d62c6934590031a5f2)
180for examples.
danakj6e25f742022-12-01 21:47:42181
danakjbb4d0c772023-10-13 13:22:28182Rust libraries should use the
183[`rust_static_library`](
184https://source.chromium.org/chromium/chromium/src/+/main:build/rust/rust_static_library.gni)
185GN template (not the built-in `rust_library`) to integrate properly into the
186mixed-language Chromium build and get the correct compiler options applied to
187them.
danakj6e25f742022-12-01 21:47:42188
danakjbb4d0c772023-10-13 13:22:28189The [CXX](https://cxx.rs) tool is used for generating C++ bindings to Rust
190code. Since it requires explicit declarations in Rust, an wrapper shim around a
191pure Rust library is needed. Add these Rust shims that contain the CXX
192`bridge` macro to the `cxx_bindings` GN variable in the `rust_static_library`
193to have CXX generate a C++ header for that file. To include the C++ header
194file, rooted in the `gen` output directory, use
danakj6e25f742022-12-01 21:47:42195```
danakjbb4d0c772023-10-13 13:22:28196#include "the/path/to/the/rust/file.rs.h"
danakj6e25f742022-12-01 21:47:42197```
198
danakj6e25f742022-12-01 21:47:42199# Using VSCode
200
2011. Ensure you're using the `rust-analyzer` extension for VSCode, rather than
202 earlier forms of Rust support.
danakjbb4d0c772023-10-13 13:22:282032. Run `gn` with the `--export-rust-project` flag, such as:
204 `gn gen out/Release --export-rust-project`.
danakj6e25f742022-12-01 21:47:422053. `ln -s out/Release/rust-project.json rust-project.json`
2064. When you run VSCode, or any other IDE that uses
207 [rust-analyzer](https://rust-analyzer.github.io/) it should detect the
208 `rust-project.json` and use this to give you rich browsing, autocompletion,
209 type annotations etc. for all the Rust within the Chromium codebase.