Adding a third-party Rust library

This document describes how to import a new third-party Rust library from https://crates.io into Chromium. Such an import is a prerequisite for depending on such a library from:

  • Chromium's first-party code (e.g. //chrome, or //components)
  • Projects that reuse Chromium's //third_party_rust such as Pdfium, or V8.
  • Other third-party dependencies (e.g. //third_party/cloud_authenticator/cbor)

Reviews

//third_party/rust/OWNERS-review-checklist.md requires that appropriate approvals are secured before landing CLs that import new crates.

All third-party libraries (not just Rust) need to go through third-party review. See //docs/adding_to_third_party.md for instructions.

Importing a crate from crates.io

Third-party crates (from crates.io) that Chromium depends on are described by two files:

  • //third_party/rust/chromium_crates_io/Cargo.toml. This file defines the set of crates directly depended on from first-party code (from Chromium first-party code, but also from Pdfium, V8, etc.). Their transitive dependencies don't need to be listed, because they will be automatically identified and covered by tools like gnrt. The file is a standard Cargo.toml file, even though the crate itself is never built - it is only used to enable/disable crate features, specify crate versions, etc.
  • //third_party/rust/chromium_crates_io/gnrt_config.toml. This file defines Chromium-specific, cargo-agnostic metadata like: - Configuring certain aspects of Chromium build (e.g. allow_unsafe, allow_unstable_features, extra_src_roots, group = "test", etc.) - Specifying licensing information when it can't be automatically inferred (e.g. pointing out license_files with non-standard filenames).

To import a third-party crate follow the steps below:

  1. Change directory to the root src/ dir of Chromium.
  2. Add the crate to //third_party/rust/chromium_crates_io/Cargo.toml:
    • vpython3 ./tools/crates/run_gnrt.py add foo to add the latest version of foo.
    • vpython3 ./tools/crates/run_gnrt.py add [email protected] to add a specific version of foo.
    • Or, edit //third_party/rust/chromium_crates_io/Cargo.toml by hand, finding the version you want from crates.io.
  3. Download the crate's files:
    • ./tools/crates/run_gnrt.py vendor to download the new crate.
    • This will also apply any patches in //third_party/rust/chromium_crates_io/patches. See //third_party/rust/chromium_crates_io/patches/README.md for more details.
  4. Exempt vendored code from inclusive-language checks - e.g.: infra/update_inclusive_language_presubmit_exempt_dirs.sh > infra/inclusive_language_presubmit_exempt_dirs.txt
  5. (optional) If the crate is only to be used by tests and tooling, then specify the "test" group in //third_party/rust/chromium_crates_io/gnrt_config.toml:
    [crate.foo]
    group = "test"
    
  6. Generate the BUILD.gn file for the new crate:
    • vpython3 ./tools/crates/run_gnrt.py gen
  7. Add //third_party/rust/crate_name/OWNERS
  8. Add the new files to git:
    • git add -f third_party/rust/chromium_crates_io/vendor. (The -f is important, as files may be skipped otherwise from a .gitignore inside the crate.)
    • git add third_party/rust
  9. Upload the CL and get a review from //third_party/rust/OWNERS (check third_party/rust/OWNERS-review-checklist.md to see what to expect).

Note that at this point the new crate is still not seen by gn nor ninja, and is not covered by CQ. To make the new crate part of the build, you need to add a deps edge between an existing build target and the newly added //third_party/rust/some_crate/v123:lib target. This will allow autoninja -C out/Default third_party/rust/some_crate/v123:lib to work. Additionally, this will help CQ to prevent regressions when updating rustc or enabling new Rust warnings.

Security

If a shipping library needs security review (has any unsafe), and the review finds it‘s not satisfying the rule of 2, then move it to the "sandbox" group in //third_party/rust/chromium_crates_io/gnrt_config.toml to make it clear it can’t be used in a privileged process:

[crate.foo]
group = "sandbox"

If a transitive dependency moves from "safe" to "sandbox" and causes a dependency chain across the groups, it will break the gnrt vendor step. You will need to fix the new crate so that it's deemed safe in unsafe review, or move the other dependent crates out of "safe" as well by setting their group in gnrt_config.toml.

Troubleshooting

Incomplete sources or inputs listing

gnrt enumerates all .rs files as crate sources, but may need help with discovering additional files consumed with something like include_str!. So, if you see:

ERROR: file not in GN sources:
../../third_party/rust/chromium_crates_io/vendor/some_crate/README.md

Then you can:

  • Add the missing files to third_party/rust/chromium_crates_io/gnrt_config.toml - for example:

    [crate.some_crate]
    extra_input_roots = ['../README.md']
    
  • Re-generate BUILD.gn files by running: tools/crates/run_gnrt.py gen