Bug 1646280 - Improve Rust build docs. r=froydnj

The added material comes from the Oxidation wiki's FAQ and the "Building
Firefox with Rust code" MDN page:
https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Firefox/Building_Firefox_with_Rust_code

Once this commit lands, I will (a) remove the wiki FAQ entries, and (b) replace
the contents of that MDN page with a link to these build docs. There's no point
having overlapping docs, and in-tree is the best place for this information.

This commit also makes the capitalization of sub-headings more consistent.

Differential Revision: https://phabricator.services.mozilla.com/D79956
This commit is contained in:
Nicholas Nethercote 2020-06-23 05:01:23 +00:00
Родитель fa755b4aa0
Коммит 51c5270b67
1 изменённых файлов: 95 добавлений и 26 удалений

Просмотреть файл

@ -4,43 +4,51 @@
Including Rust Code in Firefox
==============================
The build system has support for building and linking Rust crates.
Rust code is built using ``cargo`` in the typical way, so it is
straightforward to take an existing Rust crate and integrate it
into Firefox.
The build system has support for building, linking, and vendoring Rust crates.
It is straightforward to take an existing Rust crate and integrate it into
Firefox.
Linking Rust Crates into libxul
Linking Rust crates into libxul
===============================
Rust crates that you want to link into libxul should be listed in the
``dependencies`` section of `toolkit/library/rust/shared/Cargo.toml <https://dxr.mozilla.org/mozilla-central/source/toolkit/library/rust/shared/Cargo.toml>`_.
``dependencies`` section of
`toolkit/library/rust/shared/Cargo.toml <https://dxr.mozilla.org/mozilla-central/source/toolkit/library/rust/shared/Cargo.toml>`_.
After adding your crate, execute ``cargo update -p gkrust-shared``
to update the ``Cargo.lock`` file. You'll also
need to add an ``extern crate`` reference to
to update the ``Cargo.lock`` file. You'll also need to add an ``extern crate``
reference to
`toolkit/library/rust/shared/lib.rs <https://dxr.mozilla.org/mozilla-central/source/toolkit/library/rust/shared/lib.rs>`_.
This ensures that the Rust code will be linked properly into libxul as well
as the copy of libxul used for gtests.
By default, all Cargo packages in the mozilla-central repository are part of
the same `workspace <https://dxr.mozilla.org/mozilla-central/source/toolkit/library/rust/shared/lib.rs>`_
the same
`workspace <https://dxr.mozilla.org/mozilla-central/source/toolkit/library/rust/shared/lib.rs>`_
and will share the ``Cargo.lock`` file and ``target`` directory in the root of
the repository. You can change this behavior by adding a path to the
``excludes`` list in the top-level ``Cargo.toml`` file. You may want to do
``exclude`` list in the top-level ``Cargo.toml`` file. You may want to do
this if your package's development workflow includes dev-dependencies that
aren't needed by general Firefox developers or test infrastructure.
Linking Rust Crates into something else
The actual build mechanism is as follows. The build system generates a special
'Rust unified library' crate, compiles that to a static library
(``libgkrust.a``), and links that into libxul, so all public symbols will be
available to C++ code. Building a static library that is linked into a dynamic
library is easier than building dynamic libraries directly, and it also avoids
some subtle issues around how mozalloc works that make the Rust dynamic library
path a little wonky.
Linking Rust crates into something else
=======================================
There currently is not any Rust code being linked into binaries other than
libxul. If you would like to do so, you'll need to create a directory with
a ``Cargo.toml`` file for your crate, and a ``moz.build`` file that contains:
To link Rust code into libraries other than libxul, create a directory with a
``Cargo.toml`` file for your crate, and a ``moz.build`` file that contains:
.. code-block:: python
RustLibrary('crate_name')
Where *crate_name* matches the name from the ``[package]`` section of your
where ``crate_name`` matches the name from the ``[package]`` section of your
``Cargo.toml``. You can refer to `the moz.build file <https://dxr.mozilla.org/mozilla-central/rev/3f4c3a3cabaf94958834d3a8935adfb4a887942d/toolkit/library/rust/moz.build#7>`_ and `the Cargo.toml file <https://dxr.mozilla.org/mozilla-central/rev/3f4c3a3cabaf94958834d3a8935adfb4a887942d/toolkit/library/rust/Cargo.toml>`_ that are used for libxul.
You can then add ``USE_LIBS += ['crate_name']`` to the ``moz.build`` file
@ -48,18 +56,40 @@ that defines the binary as you would with any other library in the tree.
.. important::
You cannot link a Rust crate into an intermediate library that will wind
up being linked into libxul. The build system enforces that only a single
You cannot link a Rust crate into an intermediate library that will be
eventually linked into libxul. The build system enforces that only a single
``RustLibrary`` may be linked into a binary. If you need to do this, you
will have to add a ``RustLibrary`` to link to any standalone binaries that
link the intermediate library, and also add the Rust crate to the libxul
dependencies as in `linking Rust Crates into libxul`_.
Where Should I put my Crate?
Standalone Rust programs
========================
It is also possible to build standalone Rust programs. First, put the Rust
program (including the ``Cargo.toml`` file and the ``src`` directory) in its
own directory, and add an empty ``moz.build`` file to the same directory.
Then, if the standalone Rust program must run on the compile target (e.g.
because it's shipped with Firefox) then add this rule to the ``moz.build``
file:
.. code-block:: python
RUST_PROGRAMS = ['prog_name']
where *prog_name* is the name of the executable as specified in the
``Cargo.toml`` (and probably also matches the name of the directory).
Otherwise, if the standalone Rust program must run on the compile host (e.g.
because it's used to build Firefox but not shipped with Firefox) then do the
same thing, but use ``HOST_RUST_PROGRAMS`` instead of ``RUST_PROGRAMS``.
Where should I put my crate?
============================
If your crate's canonical home is mozilla-central, you can put it next to the
other code in the module it belongs to.
related code in the appropriate directory.
If your crate is mirrored into mozilla-central from another repository, and
will not be actively developed in mozilla-central, you can simply list it
@ -70,12 +100,51 @@ If your crate is mirrored into mozilla-central from another repository, but
will be actively developed in both locations, you should send mail to the
dev-builds mailing list to start a discussion on how to meet your needs.
Third-party crate dependencies
==============================
Crate dependencies
==================
Third-party dependencies for in-tree Rust crates are *vendored* into the
``third_party/rust`` directory of mozilla-central. This means that a copy of
each third-party crate's code is committed into mozilla-central. As a result,
building Firefox does not involve downloading any third-party crates.
All dependencies for in-tree Rust crates are vendored into the
``third_party/rust`` directory. Currently if you add a dependency on a new
crate you must run ``mach vendor rust`` to vendor the dependencies into
that directory. In the future we hope to make it so that you only need to
vendor the dependencies in order to build your changes in a CI push.
If you add a dependency on a new crate you must run ``mach vendor rust`` to
vendor the dependencies into that directory. (Note that ``mach vendor rust``
`may not work as well on Windows <https://bugzilla.mozilla.org/show_bug.cgi?id=1647582>`_
as on other platforms.)
When it comes to checking the suitability of third-party code for inclusion
into mozilla-central, keep the following in mind.
- ``mach vendor rust`` will check that the licenses of all crates are suitable.
- You should review the crate code to some degree to check that it looks
reasonable (especially for unsafe code) and that it has reasonable tests.
- Other than that, there is no formal sign-off procedure, but one may be added
in the future.
Note that all dependencies will be vendored, even ones that aren't used due to
disabled features. It's possible that multiple versions of a crate will end up
vendored into mozilla-central.
Patching third-party crates
===========================
Sometimes you might want to temporarily patch a third-party crate, for local
builds or for a try push.
To do this, first add an entry to the ``[patch.crates-io]`` section of the
top-level ``Cargo.toml`` that points to the crate within ``third_party``. For
example
.. code-block:: toml
bitflags = { path = "third_party/rust/bitflags" }
Next, run ``cargo update -p $CRATE_NAME --precise $VERSION``, where
``$CRATE_NAME`` is the name of the patched crate, and ``$VERSION`` is its
version number. This will update the ``Cargo.lock`` file.
Then, make the local changes to the crate.
Finally, make sure you don't accidentally land the changes to the crate or the
``Cargo.lock`` file.