# Rust third-party code

This directory contains third-party Rust libraries from https://crates.io
(and sometimes thin wrappers around them for Chromium interop).

[TOC]

## gnrt: Cargo.toml => vendor + BUILD.gn + README.chromium

Third-party libraries from [crates.io](https://crates.io),
depend on Cargo as a build system.
Chromium uses `gnrt` tool to automate

* Vendoring crates sources into Chromium repository
* Generating `BUILD.gn` and `README.chromium` files
  based on crate's `Cargo.toml`.

The tool can be found in `//tools/crates/gnrt`
and is typically invoked using `//tools/crates/run_gnrt.py`.

### Directory structure for third-party crates

The directory structure for a crate "foo" version 3.4.2 is:

```
//third_party/
    rust/
        foo/
            wrapper/             (optional FFI glue or Chromium integration)
            v3/                  (version 3.4.2 maps to the v3 epoch)
                BUILD.gn         (generated by gnrt gen)
                README.chromium  (generated by gnrt vendor)
        chromium_crates_io/
            vendor/
                foo-v3/  (sources downloaded from crates.io by gnrt vendor)
            patches/
                foo-v3/  (patches automatically applied during gnrt vendor)
                    0001-Some-changes.diff
                    0002-Other-changes.diff
            Cargo.toml        (version and enabled features of "foo")
            Cargo.lock
            gnrt_config.toml  (additional configuration of "foo")
```

TODO(https://crbug.com/417250983): Patch directory should be epoch-specific.

Most of the files above are managed automatically by `gnrt`.
The only "foo"-specific manually-authored files and directories are:

* `//third_party/rust/Cargo.toml`
* `//third_party/rust/gnrt_config.toml`
* `//third_party/rust/chromium_crates_io/patches/`
  (see also
  [`//third_party/rust/chromium_crates_io/patches/README.md`](chromium_crates_io/patches/README.md))
* `//third_party/rust/foo/wrapper

There are also other, non-crate-specific files such as:

* `//third_party/rust`:
    - `.md` - this doc and other docs
    - `OWNERS`, `PRESUBMIT.py`
* `//third_party/rust/chromium_crates_io`:
    - `BUILD.gn.hbs` - template for `BUILD.gn` files
    - `README.chromium.hbs` - template for `README.chromium` files
    - `PRESUBMIT.py`
    - `.py` helper scripts used by `PRESUBMIT.py` and by `//tools/crates`.
    - Somewhat obsolete `cargo vet`-support items - we keep
      `supply-chain/audits.toml` to preserve Chromium audits that are imported
      into https://github.com/google/rust-crate-audits/blob/main/sources.list)
    - Various infrastructure pieces to disable auto-formatting of the vendored
      files (e.g. `.gitattributes`, `.rustfmt.toml`, `.style.yapf`, etc.)

# Importing new third-party crates

See [`README-importing-new-crates.md`](README-importing-new-crates.md)
for instructions on how to import a crate from https://crates.io into Chromium.

# Updating existing third-party crates

Third-party crates will get updated semi-automatically through the process
described in
[`//tools/crates/create_update_cl.md`](../../tools/crates/create_update_cl.md).
If you nevertheless need to manually update a crate to its latest minor or major
version, then follow the steps below.  To facilitate easier review, we recommend
uploading separate patchsets for 1) manual changes, and 2) tool-driven,
automated changes.

1. Change directory to the root `src/` dir of Chromium.
1. Update the versions in `//third_party/rust/chromium_crates_io/Cargo.toml`.
   * `vpython3 ./tools/crates/run_gnrt.py update <crate name>`.
   * Under the hood this invokes `cargo update` and accepts the same
     [command line parameters](https://doc.rust-lang.org/cargo/commands/cargo-update.html#update-options).
     In particular, you may need to specify `--breaking` when working on
     major version updates.
1. Download any updated crate's files:
   * `./tools/crates/run_gnrt.py vendor`
1. Add the downloaded 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.
1. Generate the `BUILD.gn` files
   * `vpython3 ./tools/crates/run_gnrt.py gen`
   * Or, directly through (nightly) cargo:
     `cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gen`
1. Add the generated files to git:
   * `git add third_party/rust`

# 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>/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.

See
[`//docs/rust-ffi.md`](../../docs/rust/ffi.md)
for information on C++/Rust FFI.
