在 Firefox 中包含 Rust 代码¶
此页面说明如何添加、构建、链接和进行 Rust crate 的版本控制。
该 代码文档 说明了如何在 Firefox 中编写和使用 Rust 代码。该 测试文档 说明了如何在 Firefox 中测试和调试 Rust 代码。
将 Rust crate 链接到 libxul¶
您希望链接到 libxul 的 Rust crate 应列在 toolkit/library/rust/shared/Cargo.toml 的 dependencies
部分中。您还必须向 toolkit/library/rust/shared/lib.rs 添加一个 extern crate
引用。这确保了 Rust 代码将被正确链接到 libxul 以及用于 gtest 的 libxul 副本。(即使 Rust 2018 大多不需要 extern crate
声明,这些声明也是必要的,因为 gkrust 设置非常规。)
添加 crate 后,执行 cargo update -p gkrust-shared
以更新 Cargo.lock
文件。在您更改 Cargo.toml
文件中的依赖项时,也需要执行此操作。如果您不这样做,您将收到一个构建错误,提示 **“错误:锁定文件 /home/njn/moz/mc3/Cargo.lock 需要更新,但传递了 –frozen 以阻止此操作”**。
默认情况下,mozilla-central 存储库中的所有 Cargo 包都是同一个 工作区 的一部分,并将共享存储库根目录中的 Cargo.lock
文件和 target
目录。您可以通过在顶级 Cargo.toml
文件中添加路径到 exclude
列表来更改此行为。如果您的包的开发工作流程包含一般 Firefox 开发人员或测试基础设施不需要的 dev-dependencies,您可能希望执行此操作。
实际的构建机制如下。构建系统生成一个特殊的“Rust 统一库”crate,将其编译为静态库(libgkrust.a
),并将该库链接到 libxul 中,因此所有公共符号都可用于 C++ 代码。构建链接到动态库的静态库比直接构建动态库更容易,并且还可以避免一些关于 mozalloc 如何工作以及使 Rust 动态库路径稍微有点奇怪的微妙问题。
将 Rust crate 链接到其他内容¶
要将 Rust 代码链接到 libxul 以外的库,请创建一个包含 crate 的 Cargo.toml
文件和包含以下内容的 moz.build
文件的目录
RustLibrary('crate_name')
其中 crate_name
与 Cargo.toml
的 [package]
部分中的名称匹配。您可以参考 moz.build 文件 和 Cargo.toml 文件,它们用于 libxul。
然后,您可以将 USE_LIBS += ['crate_name']
添加到定义二进制文件的 moz.build
文件中,就像处理树中的任何其他库一样。
重要
您不能将 Rust crate 链接到最终将链接到 libxul 的中间库。构建系统强制执行只能将单个 RustLibrary
链接到二进制文件。如果您需要执行此操作,则必须添加一个 RustLibrary
以链接到链接中间库的任何独立二进制文件,并将 Rust crate 添加到 libxul 依赖项中,如 将 Rust crate 链接到 libxul 中所示。
条件编译¶
编辑 tool/library/rust/gkrust-features.mozbuild 以将构建标志公开为 Cargo 特性。
独立 Rust 程序¶
也可以构建独立的 Rust 程序。首先,将 Rust 程序(包括 Cargo.toml
文件和 src
目录)放在其自己的目录中,并在同一目录中添加一个空的 moz.build
文件。
然后,如果独立 Rust 程序必须在编译目标上运行(例如,因为它与 Firefox 一起发布),则向 moz.build
文件添加以下规则
RUST_PROGRAMS = ['prog_name']
其中 prog_name 是 Cargo.toml
中指定的可执行文件的名称(并且可能也与目录的名称匹配)。
否则,如果独立 Rust 程序必须在编译主机上运行(例如,因为它用于构建 Firefox 但不与 Firefox 一起发布),则执行相同的操作,但使用 HOST_RUST_PROGRAMS
而不是 RUST_PROGRAMS
。
我应该把我的 crate 放在哪里?¶
如果您的 crate 的规范位置是 mozilla-central,您可以将其放在相应目录中相关代码的旁边。
如果您的 crate 从另一个存储库镜像到 mozilla-central,并且不会在 mozilla-central 中积极开发,您可以简单地将其列为具有版本号的 crates.io
样式依赖项,并将其版本控制到 third_party/rust
目录中。
如果您的 crate 从另一个存储库镜像到 mozilla-central,但将在两个位置积极开发,则应向 dev-builds 邮件列表发送邮件,以开始讨论如何满足您的需求。
第三方 crate 依赖项¶
树内 Rust crate 的第三方依赖项会被版本控制到 mozilla-central 的 third_party/rust
目录中。这意味着每个第三方 crate 代码的副本都会提交到 mozilla-central。因此,构建 Firefox 不涉及下载任何第三方 crate。
如果您添加对新 crate 的依赖项,则必须运行 mach vendor rust
以将依赖项版本控制到该目录中。(请注意,mach vendor rust
在 Windows 上可能不如 在其他平台上那样有效。)
在检查第三方代码是否适合包含到 mozilla-central 时,请记住以下几点。
mach vendor rust
将检查所有 crate 的许可证是否合适。mach vendor rust
将运行cargo vet
以确保 crate 已被审核。如果没有,您将必须使用mach cargo vet
对其进行审核,以检查代码是否合理(尤其是 unsafe 代码)以及是否存在合理的测试。所有版本控制的 crate 都必须经过审核。第三方 crate 测试不会运行,这意味着大型测试装置会使 mozilla-central 膨胀。考虑与上游合作,使用
[package] exclude = ...
标记这些测试装置,如 此处 所述。如果您指定对分支的依赖项,请将其固定到特定版本,否则,其他人将在每次分支更新时运行
./mach vendor rust
时获得意外的更改。有关此问题已解决的情况,请参阅 错误 1612619。除此之外,没有正式的签核程序,但将来可能会添加。
请注意,所有依赖项都将被版本控制,即使由于禁用了特性而未使用的依赖项也是如此。可能有多个版本的 crate 最终会被版本控制到 mozilla-central 中。
修补第三方 crate¶
有时您可能希望暂时修补第三方 crate,用于本地构建或 try 推送。
为此,首先在顶级 Cargo.toml
的 [patch.crates-io]
部分添加一个条目,该条目指向 third_party
中的 crate。例如
bitflags = { path = "third_party/rust/bitflags" }
接下来,运行 cargo update -p $CRATE_NAME --precise $VERSION
,其中 $CRATE_NAME
是已修补 crate 的名称,$VERSION
是其版本号。这将更新 Cargo.lock
文件。
然后,对 crate 进行本地更改。
最后,确保您不会意外地将对 crate 或 Cargo.lock
文件的更改合并到代码库中。
有关涉及第三方板条箱的更复杂工作流程的示例,请参阅mp4parse-rust/README.md。它描述了一个托管在 GitHub 上的板条箱的工作流程,以及通过 GitHub 拉取请求进行更改的工作流程,但所有拉取请求都必须在合并到 mozilla-central 之前进行测试。