blob: fbe5142f6bcf2ab3d48ca317dc2c4b2843cf9dd1 [file] [log] [blame] [view]
# External Rust crates
Fuchsia uses external Rust crates. External Rust crates are placed in
[`//third-party/rust_crates/vendor`][external-vendor]. This set of crates is
based on the dependencies listed in
[`//third_party/rust_crates/Cargo.toml`][external-cargo-toml].
Generally, adding or updating an external crate involves the following:
- Calculating the dependencies of your external crate.
Note: Pay attention to transitive dependencies. An external crate may
depend on other external crates. List all the new crates that end up
being brought in along with the originally intended crate, within the OSRB
review.
- Requesting Open Source Review Board (OSRB) approval.
- For more information, see either the [Adding an external crate](#adding_an_external_crate)
or [Updating an external crate](#updating_an_external_crate) section of this
document.
- Waiting to be granted OSRB approval.
Warning: You must receive approval from the OSRB _before_ pushing a commit to
Gerrit that adds an external crate. Do not request a code review for adding an
external crate until you have approval from the OSRB.
- Uploading the change for code review.
## Adding an external crate
If you don't find an existing crate that you want to use,
you may want to add an external crate to Fuchsia.
To add an external crate, do the following:
1. Change to Fuchsia repository's base directory.
For example, if your fuchsia directory is `~/fuchsia`, run the following
command:
```posix-terminal
cd ~/fuchsia
```
1. Add an entry in
[`third_party/rust_crates/Cargo.toml`][external-cargo-toml]
for the crate that you want to add.
1. Run the following command to download your desired crate(s) and calculate
that crate's dependencies:
Note: On Linux, you need to install `pkg-config` with your chosen package
manager prior to running this command.
```posix-terminal
fx update-rustc-third-party
```
`fx update-rustc-third-party` downloads all of the crates listed in
[`rust_crates/Cargo.toml`][external-cargo-toml] as well as their
dependencies, places the downloaded crates in the `vendor` directory, and
then updates `Cargo.toml` and `Cargo.lock`.
You may need to provide additional configuration in a `[gn.package.<crate>]`
section inside the `Cargo.toml` file. For crates that use a `build.rs`
script, this configuration replaces the script, which is intentionally
unsupported by the build system. This configuration is used by
`cargo-gnaw`, which generates the GN rules from the Cargo.toml file.
See [cargo-gnaw's README][cargo-gnaw-readme]
for more details.
1. Run the following command to perform a build test:
```posix-terminal
fx set core.x64 && fx build
```
1. Request OSRB approval by doing the following:
- Create an issue with the
[Open Source Review Board (OSRB) template](https://bugs.fuchsia.dev/p/fuchsia/issues/entry?template=Open+Source+Review+Board+).
- In the issue, do the following:
- Leave the **Owner** field blank.
- The OSRB team meets regularly to review the issues.
Please allow about a week for a response.
- Specify all of the crates that you want to **add** (no need to list
previously approved crates). Include the crate(s) that you're adding
as well as the dependency crates identified after running
`fx update-rustc-third-party`.
- If there are any files in the source repository that are not included
when vendored, specify those files in your issue to the OSRB. For
example, font files that are only used for testing but are excluded
when the crate is vendored would need to be included in an OSRB issue.
Note: As part of the OSRB review, you may be asked to import only a subset
of the files in an external crate. See
[Importing a subset of files in a crate](#importing_a_subset_of_files_in_a_crate)
for more information.
1. If you receive OSRB approval, upload the change to Gerrit for review.
Include the OSRB Issue ID number in the change.
Warning: You must receive approval from the OSRB _before_ pushing a
commit to Gerrit that adds an external crate. Do not request a code
review for adding an external crate until you have approval from the OSRB.
1. Add an [OWNER][owners-file]
of the external rust crate directory as a code reviewer. You must get a
`Code Review Label +2` from one of the repository's owners.
1. If you have the ability to submit an approved change to the
Commit Queue (CQ), [submit your change](https://gerrit-review.googlesource.com/Documentation/intro-user.html#submit)
to merge that change into [third_party/rust_crates][external-crates].
If you don't have the ability to submit an approved change, reply to your
Gerrit change and request that one of the repository owners submit your
change.
For more information about the associated actions for each contributor
role, see [Role matrix](/docs/contribute/community/contributor-roles.md).
## Updating an external crate
Warning: You must receive approval from the OSRB _before_ pushing a commit to
Gerrit if updating an external crate changes the license or pulls in a new crate
as a dependency. Do not request a code review until you have approval from the
OSRB in these circumstances.
To update an external crate, do the following:
1. Increase the patch number of the crate in
[`third_party/rust_crates/Cargo.toml`][external-cargo-toml].
1. Run the following command:
```posix-terminal
fx update-rustc-third-party
```
You may need to update or provide additional configuration
in `[gn.package.<crate>]` sections inside the Cargo.toml file. For crates
that use a `build.rs` script this configuration replaces the script,
which is intentionally unsupported by of the build system. This
configuration is used by `cargo-gnaw`, which generates the GN rules from
the `Cargo.toml` file.
See [cargo-gnaw's README][cargo-gnaw-readme] for more details.
1. Run the following command to perform a build test:
```posix-terminal
fx set core.x64 && fx build
```
1. Request OSRB approval by doing the following:
- Create an issue with the
[Open Source Review Board (OSRB) template](https://bugs.fuchsia.dev/p/fuchsia/issues/entry?template=Open+Source+Review+Board+).
- In the issue, do the following:
- Leave the **Owner** field blank.
- The OSRB team meets regularly to review the issues.
Please allow about a week for a response.
- Specify all of the crates that you want to add. Include the crate(s)
that you're adding as well as the dependency crates identified after
running `fx update-rustc-third-party`.
- If there are any files in the source repository that are not included
when vendored, specify those files in your issue to the OSRB. For
example, font files that are only used for testing but are excluded
when the crate is vendored would need to be included in an OSRB issue.
Note: As part of the OSRB review, you may be asked to import only a subset
of the files in an external crate. See
[Importing a subset of files in a crate](#importing_a_subset_of_files_in_a_crate)
for more information.
1. If you receive OSRB approval, upload the change for review to
Gerrit. Include the OSRB Issue ID number in the change.
1. Add an [OWNER][owners-file]
of the external rust crate repository as a code reviewer. You must get a
`Code Review Label +2` from one of the repository's owners.
1. If you have the ability to submit an approved change to the
Commit Queue (CQ), [submit your change](https://gerrit-review.googlesource.com/Documentation/intro-user.html#submit)
to merge that change into [third_party/rust_crates][external-crates].
If you don't have the ability to submit an approved change, reply to your
Gerrit change and request that one of the repository owners submit your
change.
For more information about the associated actions for each contributor
role, see [Role matrix](/docs/contribute/community/contributor-roles.md).
## Adding a new mirror
When actively contributing to an upstream repository or
maintaining a long-lived fork of a Fuchsia repository, it can be useful to
import a crate using a full git repository rather than Cargo's vendoring tools.
While this approach is useful, it has significant overhead compared to the
default flow and should be approached with caution.
Warning: You must receive approval from the OSRB _before_ pushing a commit to
Gerrit that adds or updates an external crate. Do not request a code
review for adding or updating an external crate until you have approval
from the OSRB.
1. Request the addition of a mirror on *fuchsia.googlesource.com*.
1. Add the mirror to the [Jiri manifest][jiri-manifest] for the Rust runtime.
1. Add a patch section for the crate to the workspace.
1. Run the update script.
## Importing a subset of files in a crate
In some cases, you may want to import only a subset of files in a crate. For
example, there may be an optional license in the
external repository that's incompatible with Fuchsia's license requirements.
Here's [an example](https://fuchsia-review.googlesource.com/c/fuchsia/+/369174)
OSRB review in which this happened.
To do this, you'll need to add the crate's files to `/third_party/rust_crates/forks`.
1. Follow the [instructions for adding an external crate](#adding_an_external_crate).
1. After running `fx update-rustc-third-party`, move the downloaded copy of your
crate from `/third_party/rust_crates/vendor/<my_crate>` to
`/third_party/rust_crates/forks/<my_crate>`.
1. Make the changes you need to make to the imported files.
1. Add a line to the `[patch.crates-io]` section of
`/third_party/rust_crates/Cargo.toml` to point to your new crate:
```
[patch.crates-io]
...
my_crate = { path = "forks/<my_crate>" }
...
```
1. Re-run `fx update-rustc-third-party` and `fx build`.
1. Add a `/third_party/rust_crates/forks/<my_crate>/README.fuchsia` file which matches the format of
other crates' `README.fuchsia`s there. See [/third_party/rust_crates/forks/README.md] for what it
should contain.
## Unicode crates
If the project requires importing a new external crate to handle
functionality related to Unicode and internationalization, prefer crates from
the [UNIC project](https://crates.io/crates/unic){: .external} when available.
### Exempted non-UNIC crates
The following non-UNIC crates are already vendored and are exempted:
* `unicode-bidi`
* `unicode-normalization`
* `unicode-segmentation`
* `unicode-width`
* `unicode-xid`
### Rationale for standardization
UNIC crates have distinct advantages over other crates:
* UNIC crates are developed in a single repo, with shared common code and a
single version scheme.
* Independently developed crates do not share a common release schedule,
versioning scheme, or adherence to any particular version of the Unicode
standard.
* UNIC crates are generated from a consistent set of Unicode data files.
* Each of the independent crates uses an arbitrary version and subset of
the data. For example, different crates might have different assumptions
about whether a particular code point is assigned, what its properties
are, etc.
* The UNIC project is aiming for comprehensive feature coverage, to be like
[ICU](http://site.icu-project.org/){: .external} for Rust. If the project
succeeds, our dependencies on unrelated Unicode crates should be
reduced over time.
## OWNERS files
`OWNERS` files are maintained for all of the external Rust crates to
indicate who is responsible for their reviews and updates. These files are
generated from a combination of build graph metadata and an explicit
override file.
### Running the tool
The tool discovers which build targets depend on a given crate, which means it
needs the metadata from the completion of a maximal "kitchen sink" build:
1. Include `//bundles/buildbot:core` and `//bundles:kitchen_sink` in your build
2. Run `fx build`
3. Run `fx update-rust-3p-owners --num-threads <NUM_THREADS>`. It's usually a good idea to limit
the number of threads to 50% of available CPUs (see [#75382] for details).
[#75382]: https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=75382
### Adding overrides
Some crates have more users than can be relied upon to maintain
(see [Bystander effect]{: .external}). Others implement behavior specific to a
domain like security and we would prefer for a specific team to be responsible
for reviews of the code.
In these cases, add an entry to `//third_party/rust_crates/owners.toml` with
the path(s) to other `OWNERS` files to reference, then re-run the tool.
This replaces the reverse-dependency metadata ownership with the overridden
paths.
[Bystander effect]: https://en.wikipedia.org/wiki/Bystander_effect
### Update frequency
A member of the Rust on Fuchsia team is currently responsible for running the
tool on a regular cadence. See [https://fxbug.dev/73348](https://fxbug.dev/73348)
to track the process of automating updates to OWNERS files.
## Overriding locally
It can be useful to override a third party crate if you're contributing upstream
and want to run in-tree builds or tests. That can be achieved with the following
steps.
1. Clone (or symlink) the upstream repository under
`third_party/rust_crates/forks/<my_crate>`.
1. Add the override to the `[patch.crates-io]` section in
`third_party/rust_crates/Cargo.toml`.
```
[patch.crates-io]
my_crate = { path = "forks/<my_crate>" }
```
1. You must make sure that the version under the crate's `Cargo.toml` matches
all references to that crate in `third_party/rust_crates/Cargo.toml`.
1. Run `fx update-rustc-third-party`.
## Troubleshooting
### Broken Config
After running `fx update-rustc-third-party`, if you encounter an error like
this:
```
Generating GN file from /$HOME/fuchsia/third_party/rust_crates/Cargo.toml
Error: GNaw config exists for crates that were not found in the Cargo
build graph:
library crate, package handlebars version 2.0.0-beta.2
library crate, package core-foundation-sys version 0.7.0
library crate, package pulldown-cmark version 0.6.0
library crate, package nix version 0.18.0
```
You can fix this issue commenting out your fuchsia target in `.cargo/config`:
```
[build]
...
target = "x86_64-fuchsia"
```
After commenting, it becomes:
```
[build]
...
# target = "x86_64-fuchsia"
```
This issue is being tracked [upstream](https://github.com/rust-lang/cargo/issues/8462){: .external}.
[external-crates]: /third_party/rust_crates/
[external-cargo-toml]: /third_party/rust_crates/Cargo.toml
[external-vendor]: /third_party/rust_crates/vendor
[cargo-gnaw-readme]: /tools/cargo-gnaw/README.md
[osrb-process]: /docs/contribute/governance/policy/osrb-process.md#process_for_adding_external_code_to_new_repositories
[jiri-manifest]: https://fuchsia.googlesource.com/manifest/+/main/runtimes/rust "Jiri manifest"
[owners-file]: /third_party/rust_crates/OWNERS