Building Firefox with Rust code

In May 2015 the Rust programming language reached its 1.0 stability milestone, and various experiments with writing parts of Gecko in Rust began. Rust code first shipped in August 2016 with the release of Firefox 48. It became a requirement for building Gecko in February 2017 with Firefox 54.

This page is a rough guide for people working in this area. See also the corresponding build system documentation.

Adding Rust code

We generally target stable Rust, but sometimes issues temporarily require a beta or custom toolchain build. Our goal is to always ship a Firefox release build with a stable Rust toolchain release. If you don't have rust already, use the rustup tool to install it and update as new releases become available, or use the ./mach bootstrap command.

The build system will generate a special 'rust unified library' crate, compiled to a static library (libgkrust.a) which is in turn linked into XUL, so all public symbols will be available to C++ code.

If you have new Rust libraries that code in libxul calls directly, then you should add the appropriate extern crate lines in toolkit/library/rust/shared/, and add those libraries (crates) as dependencies in toolkit/library/rust/Cargo.toml. If you want to call code in the "e10s" crate, you would add:

extern crate e10s;

to toolkit/library/rust/shared/; you would also need to specify the path to that crate in the dependencies section of toolkit/library/rust/shared/Cargo.toml:

e10s = { path = "../../../../path/from/srcdir/e10s" }

The e10s crate must also be checked into the tree at the appropriate path. If the e10s crate depends on any other crates, their sources must also be checked into the tree, and e10s's Cargo.toml must have path attributes for each of its dependencies, and so on. This is automated by the mach vendor command, which installs the dependencies in third_party/rust. Be sure the licenses of all dependent crates are compatible.

Cargo.lock files have also been checked in, so you will need to update those as well when appropriate.

Crates for unit tests can be added in a similar fashion to the files in toolkit/library/gtest/rust/.

If your crate has optional features that aren't normally turned on, you are strongly encouraged to remove dependencies for those features when importing code so the build system doesn't require that (unused) code to live in-tree.

The build system will check that there's only one copy of a given crate in a build; this was a deliberate decision to try and avoid code bloat in libxul.  If this turns out to be a serious problem in practice, we can look into ways of relaxing that check.

If you need to locally patch a third-party crate, you'll need to add a [replace] section to the referencing Cargo.toml to declare that the vendored source shouldn't match the upstream release.  This works even if you use the existing vendored source location, but be aware that other vendor updates could clobber your patch in that case.

Testing Rust code

There's a simple linkage unit test in the tree. You can use it to check that Rust is enabled and working with your build setup.

./mach gtest rust.*

Look for the rust.CallFromCpp test to pass, along with any others.

Disabling Rust code

Support for building without Rust code was removed in bug 1284816. For Firefox 54 it's possible to build without Rust by patching out that and subsequent changes, but starting with Firefox 55 this becomes increasingly difficult and affects user security and available features.