| # Rust in Chromium |
| |
| [TOC] |
| |
| # Why? |
| |
| Handling untrustworthy data in non-trivial ways is a major source of security |
| bugs, and it's therefore against Chromium's security policies |
| [to do it in the Browser or Gpu process](../docs/security/rule-of-2.md) unless |
| you are working in a memory-safe language. |
| |
| Rust provides a cross-platform memory-safe language so that all platforms can |
| handle untrustworthy data directly from a privileged process, without the |
| performance overheads and complexity of a utility process. |
| |
| # Status |
| |
| The Rust toolchain is enabled for and supports all platforms and development |
| environments that are supported by the Chromium project. The first milestone |
| to include full production-ready support was M119. |
| |
| Rust is approved by Chrome ATLs for production use in |
| [certain third-party scenarios](../docs/adding_to_third_party.md#Rust). |
| |
| For questions or help, reach out to `rust-dev@chromium.org` or `#rust` on the |
| [Chromium Slack](https://www.chromium.org/developers/slack/). |
| |
| If you use VSCode, we have [additional advice below](#using-vscode). |
| |
| # Adding a third-party Rust library |
| |
| Third-party libraries are pulled from [crates.io](https://crates.io), but |
| Chromium does not use Cargo as a build system. |
| |
| ## Third-party review |
| |
| All third-party crates need to go through third-party review. See |
| [//docs/adding_to_third_party.md](adding_to_third_party.md) for instructions on |
| how to have a library reviewed. |
| |
| ## Importing a crate from crates.io |
| |
| The `//third_party/rust/third_party.toml` crate defines the set of crates |
| depended on from first-party code. Any transitive dependencies will be found |
| from those listed there. The file is a subset of a |
| [standard `Cargo.toml` file](https://doc.rust-lang.org/cargo/reference/manifest.html), |
| but only listing the `[dependencies]` section. |
| |
| To use a third-party crate "bar" version 3 from first party code, add the |
| following to `//third_party/rust/third_party.toml` in `[dependencies]`: |
| ```toml |
| [dependencies] |
| bar = "3" |
| ``` |
| |
| To enable a feature "spaceships" in the crate, change the entry in |
| `//third_party/rust/third_party.toml` to include the feature: |
| ```toml |
| [dependencies] |
| bar = { version = "3", features = [ "spaceships" ] } |
| ``` |
| |
| ### Generating `BUILD.gn` files for third-party crates |
| |
| To generate `BUILD.gn` files for all third-party crates, and find missing |
| transitive dependencies to download, use the `gnrt` tool: |
| |
| 1. Change directory to the root `src/` dir of Chromium. |
| 1. Run `vpython3 ./tools/crates/run_gnrt.py gen` to build and run gnrt with the `gen` action. |
| |
| Or, to directly build and run gnrt with the system Rust toolchain: |
| |
| 1. Change directory to the root `src/` dir of Chromium. |
| 1. Build and run `gnrt gen`: |
| `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`. |
| |
| This will generate a `BUILD.gn` file for each third-party crate. The `BUILD.gn` |
| file changes will be visible in `git status` and can be added with `git add`. |
| |
| ### Downloading missing third-party crates |
| |
| To download crate "foo", at version 4.2.3: |
| 1. Change directory to the root src/ dir of Chromium. |
| 1. Run `gnrt` with the `download` action. e.g. |
| `vpython3 ./tools/crates/run_gnrt.py download --security-critical=yes --shipped=yes foo 4.2.3` |
| |
| This will download the crate and unpack it into |
| `//third_party/rust/foo/v4/crate`. The entire `v4` directory, which includes the |
| `crate` subdirectory as well as a generated `README.chromium` file, should be |
| added to the repository with `git add third_party/rust/foo/v4`. |
| |
| Once all the crates are downloaded and `gnrt gen` completes, a CL can be |
| uploaded to go through third-party review. |
| |
| ### Patching third-party crates. |
| |
| You may patch a crate in tree, but save any changes made into a diff file in |
| a `patches/` directory for the crate. The diff file should be generated by |
| `git-format-patch` each new patch numbered consecutively so that they can be |
| applied in order. For example, these files might exist if the "foo" crate was |
| patched with a couple of changes: |
| |
| ``` |
| //third_party/rust/foo/v4/patches/0001-Edit-the-Cargo-toml.diff |
| //third_party/rust/foo/v4/patches/0002-Other-changes.diff |
| ``` |
| |
| The recommended procedure to create such patches is: |
| |
| 1. Commit the plain new version of the crate to your local git branch |
| 2. Modify the crate as necessary |
| 3. Commit that modified version |
| 4. Use `git format-patch <unpatched version>` to generate the patch files |
| 5. Add the patch files in a new, third, commit |
| 6. Squash them, or rely on `git cl upload` doing so |
| |
| ### Updating existing third-party crates |
| |
| To update a crate "foo" to the latest version you must just re-import it at this |
| time. To update from version "1.2.0" to "1.3.2": |
| 1. Remove the `//third_party/rust/foo/v1/crate` directory, which contains the |
| upstream code. |
| 1. Re-download the crate at the new version with `out/gnrt/release/gnrt download |
| foo 1.3.2`. |
| 1. If there are any, re-apply local patches with |
| `for i in $(find third_party/rust/foo/v1/patches/*); do patch -p1 < $i; done` |
| 1. Run `vpython3 ./tools/crates/run_gnrt.py gen` to re-generate all third-party |
| `BUILD.gn` files. |
| 1. Build `all_rust` to verify things are working. |
| |
| ### Directory structure for third-party crates |
| |
| The directory structure for a crate "foo" version 3.4.2 is: |
| ``` |
| //third_party/ |
| rust/ |
| foo/ |
| v3/ |
| BUILD.gn (generated by gnrt gen) |
| README.chromium (generated by gnrt download) |
| crate/ |
| Cargo.toml |
| src/ |
| ...etc... |
| patches/ |
| 0001-Edit-the-Cargo-toml.diff |
| 0002-Other-changes.diff |
| ``` |
| |
| ## Writing a wrapper for binding generation |
| |
| Most Rust libraries will need a more C++-friendly API written on top of them in |
| order to generate C++ bindings to them. The wrapper library can be placed |
| in `//third_party/rust/<cratename>/<epoch>/wrapper` or at another single place |
| that all C++ goes through to access the library. The [CXX](https://cxx.rs) is |
| used to generate bindings between C++ and Rust. |
| |
| See |
| [`//third_party/rust/serde_json_lenient/v0_1/wrapper/`]( |
| https://source.chromium.org/chromium/chromium/src/+/main:third_party/rust/serde_json_lenient/v0_1/wrapper/) |
| and |
| [`//components/qr_code_generator`]( |
| https://source.chromium.org/chromium/chromium/src/+/main:components/qr_code_generator/;l=1;drc=b185db5d502d4995627e09d62c6934590031a5f2) |
| for examples. |
| |
| Rust libraries should use the |
| [`rust_static_library`]( |
| https://source.chromium.org/chromium/chromium/src/+/main:build/rust/rust_static_library.gni) |
| GN template (not the built-in `rust_library`) to integrate properly into the |
| mixed-language Chromium build and get the correct compiler options applied to |
| them. |
| |
| The [CXX](https://cxx.rs) tool is used for generating C++ bindings to Rust |
| code. Since it requires explicit declarations in Rust, an wrapper shim around a |
| pure Rust library is needed. Add these Rust shims that contain the CXX |
| `bridge` macro to the `cxx_bindings` GN variable in the `rust_static_library` |
| to have CXX generate a C++ header for that file. To include the C++ header |
| file, rooted in the `gen` output directory, use |
| ``` |
| #include "the/path/to/the/rust/file.rs.h" |
| ``` |
| |
| # Using VSCode |
| |
| 1. Ensure you're using the `rust-analyzer` extension for VSCode, rather than |
| earlier forms of Rust support. |
| 2. Run `gn` with the `--export-rust-project` flag, such as: |
| `gn gen out/Release --export-rust-project`. |
| 3. `ln -s out/Release/rust-project.json rust-project.json` |
| 4. When you run VSCode, or any other IDE that uses |
| [rust-analyzer](https://rust-analyzer.github.io/) it should detect the |
| `rust-project.json` and use this to give you rich browsing, autocompletion, |
| type annotations etc. for all the Rust within the Chromium codebase. |