Fuchsia uses external Rust crates. External Rust crates are placed in
//third-party/rust_crates/vendor
. This set of crates is
based on the dependencies listed in
//third_party/rust_crates/Cargo.toml
.
Generally, adding or updating an external crate involves the following:
Calculating the dependencies of your external crate.
Requesting Open Source Review Board (OSRB) approval.
- For more information, see either the Adding an external crate or Updating an external crate section of this document.
Waiting to be granted OSRB approval.
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:
Change to Fuchsia repository's base directory.
For example, if your fuchsia directory is
~/fuchsia
, run the following command:cd ~/fuchsia
Add an entry in
third_party/rust_crates/Cargo.toml
for the crate that you want to add.Run the following command to download your desired crate(s) and calculate that crate's dependencies:
fx update-rustc-third-party
fx update-rustc-third-party
downloads all of the crates listed inrust_crates/Cargo.toml
as well as their dependencies, places the downloaded crates in thevendor
directory, and then updatesCargo.toml
andCargo.lock
.You may need to provide additional configuration in a
[gn.package.<crate>]
section inside theCargo.toml
file. For crates that use abuild.rs
script, this configuration replaces the script, which is intentionally unsupported by the build system. This configuration is used bycargo-gnaw
, which generates the GN rules from the Cargo.toml file. See cargo-gnaw's README for more details.After committing your change locally, run
fx update-rustc-third-party
a second time and ensure it completes successfully without producing any changes. You can rungit status
to be certain.Run the following command to perform a build test:
fx set core.x64 && fx build
Request OSRB approval by doing the following:
- Create an issue with the Open Source Review Board (OSRB) template.
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.
- Leave the Owner field blank.
If you receive OSRB approval, upload the change to Gerrit for review. Include the OSRB Issue ID number in the change.
Add an OWNER 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.If you have the ability to submit an approved change to the Commit Queue (CQ), submit your change to merge that change into third_party/rust_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.
Updating an external crate
To update an external crate, do the following:
Increase the patch number of the crate in
third_party/rust_crates/Cargo.toml
- For transitive deps (which don't appear in the root
Cargo.toml
), you can use a command likecargo +fuchsia update --manifest-path third_party/rust_crates/Cargo.toml --package $crate_name
, instead.
- For transitive deps (which don't appear in the root
Run the following command:
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 abuild.rs
script this configuration replaces the script, which is intentionally unsupported by of the build system. This configuration is used bycargo-gnaw
, which generates the GN rules from theCargo.toml
file. See cargo-gnaw's README for more details.After committing your change locally, run
fx update-rustc-third-party
a second time and ensure it completes successfully without producing any changes. You can rungit status
to be certain.Run the following command to perform a build test:
fx set core.x64 && fx build
Examine the changes for any changes in license or dependencies. If there are these types of changes, you must go through the OSRB approval process. Request OSRB approval by doing the following:
- Create an issue with the Open Source Review Board (OSRB) template.
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.
- Leave the Owner field blank.
Update OWNERS files for modified crates. See the OWNERS files section for more information on updating OWNERS files.
If/when you receive OSRB approval, upload the change for review to Gerrit. Include the OSRB Issue ID number in the change.
If there are no license or dependency changes, you may upload the change for review without going through the OSRB approval process.
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.
- Request the addition of a mirror on fuchsia.googlesource.com.
- Add the mirror to the Jiri manifest for the Rust runtime.
- Add a patch section for the crate to the workspace.
- 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 OSRB review in which this happened.
To do this, you'll need to add the crate's files to /third_party/rust_crates/forks
.
- Follow the instructions for adding an external crate.
- 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>
. - Make the changes you need to make to the imported files.
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>" } ...
Re-run
fx update-rustc-third-party
andfx build
.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 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 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.
The update-rustc-third-party
tool makes a best effort to update these files
with the limited data it has, but it can make mistakes. The update-3p-owners
tool can do better by regenerating the OWNERS files directly from our build
graph.
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:
- Run
fx set core.x64 --with //bundles/buildbot/core --with //bundles/kitchen_sink
- Run
fx update-3p-owners --rust-metadata <FUCHSIA_BUILD_DIR>/rustlang/3p-crates-metadata.json
.
Manually updating OWNERS
The OWNERS files for vendored third-party crates are built from two main sources:
- Targets that depend on third-party Rust crates have their OWNERS files
imported into the OWNERS for the crates they depend on. For example, if a
target like
src/lib/foo
depended on thebar
crate, then the OWNERS file for thebar
crate would includesrc/lib/foo/OWNERS
. - Third-party Rust crates that depend on another third-party Rust crate import
their dependency's OWNERS file into their own. For example, if the
bar
crate depended on thebaz
crate, then the OWNERS file for thebar
crate would includethird_party/rust_crates/vendor/bar-1.0.0/OWNERS
.
For version bumps of existing crates, it's usually sufficient to update the include statements to the latest version of the updated crate.
Adding overrides
Some crates have more users than can be relied upon to maintain (see Bystander effect). 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/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.
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/42152910 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.
- Clone (or symlink) the upstream repository under
third_party/rust_crates/forks/<my_crate>
. - Add the override to the
[patch.crates-io]
section inthird_party/rust_crates/Cargo.toml
.
[patch.crates-io]
my_crate = { path = "forks/<my_crate>" }
- You must make sure that the version under the crate's
Cargo.toml
matches all references to that crate inthird_party/rust_crates/Cargo.toml
. - 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-unknown-fuchsia"
After commenting, it becomes:
[build]
...
# target = "x86_64-unknown-fuchsia"
This issue is being tracked upstream.