外部 Rust crate

Fuchsia 使用外部 Rust crate。外部 Rust crate 放置在 //third-party/rust_crates/vendor 中。这组 crate 基于 //third_party/rust_crates/Cargo.toml 中列出的依赖项。

通常,添加或更新外部 crate 涉及以下步骤:

  • 计算外部 crate 的依赖项。

  • 请求 Open Source Review Board (OSRB) 批准。

  • 正在等待 OSRB 批准。

  • 上传更改以进行代码审核

添加外部 crate

如果您找不到要使用的现有 crate,不妨考虑向 Fuchsia 添加外部 crate。

如需添加外部 crate,请执行以下操作:

  1. 切换到 Fuchsia 代码库的基础目录。

    例如,如果您的 Fuchsia 目录为 ~/fuchsia,请运行以下命令:

      cd ~/fuchsia
  2. third_party/rust_crates/Cargo.toml 中为您要添加的 crate 添加条目。

  3. 运行以下命令可下载所需的 crate 并计算该 crate 的依赖项:

      fx update-rustc-third-party

    fx update-rustc-third-party 会下载 rust_crates/Cargo.toml 中列出的所有 crate 及其依赖项,将下载的 crate 放置在 vendor 目录中,然后更新 Cargo.tomlCargo.lock

    您可能需要在 Cargo.toml 文件内的 [gn.package.<crate>] 部分中提供其他配置。对于使用 build.rs 脚本的 crate,此配置会替换该脚本,因为构建系统故意不支持该脚本。cargo-gnaw 会使用此配置,并根据 Cargo.toml 文件生成 GN 规则。如需了解详情,请参阅 cargo-gnaw 的 README

    在本地提交更改后,请再次运行 fx update-rustc-third-party,并确保它成功完成且未产生任何更改。您可以运行 git status 来确认。

  4. 运行以下命令以执行构建测试:

      fx set core.x64 && fx build
  5. 请按以下步骤申请 OSRB 批准:

    • 使用 Open Source Review Board (OSRB) 模板创建问题。
    • 在问题中,执行以下操作:

      • Owner(所有者)字段留空。
        • OSRB 团队会定期开会审核相关问题。请耐心等待大约一周的时间,我们会给您回复。
      • 指定您要添加的所有 crate(无需列出之前已获批准的 crate)。添加要添加的 crate 以及运行 fx update-rustc-third-party 后识别出的依赖项 crate。
      • 如果源代码库中有任何文件在供应商化时未包含,请在向 OSRB 提交的问题中指明这些文件。例如,仅用于测试但在 crate 被供应商化时被排除的字体文件需要包含在 OSRB 问题中。
  6. 如果您获得 OSRB 批准,请将更改上传到 Gerrit 以供审核。 在更改中添加 OSRB 问题 ID 编号。

  7. 将外部 rust crate 目录的所有者添加为代码审核者。您必须从代码库的所有者之一那里获取 Code Review Label +2

  8. 如果您能够将已获批准的更改提交到提交队列 (CQ),请提交更改,以将该更改合并到 third_party/rust_crates

    如果您无法提交已获批准的更改,请回复您的 Gerrit 更改,并请求某个代码库所有者提交您的更改。

    如需详细了解每个贡献者角色的相关操作,请参阅角色矩阵

更新外部 crate

如需更新外部 crate,请执行以下操作:

  1. third_party/rust_crates/Cargo.toml 中提高了 crate 的补丁编号

    • 对于传递依赖项(未显示在 third_party_rust_crates/Cargo.toml 中),请改为运行 fx host-tool cargo update --manifest-path third_party/rust_crates/Cargo.toml --package $crate_name。该命令的输出将输出 $crate_name 已更新到的版本。接下来,检查 third_party/rust_crates/BUILD.gn 中是否有对 $crate_name 的引用,并相应地更新版本字符串。
  2. 运行以下命令:

      fx update-rustc-third-party

    您可能需要在 Cargo.toml 文件内的 [gn.package.<crate>] 部分中更新或提供其他配置。对于使用 build.rs 脚本的 crate,此配置会替换该脚本,因为构建系统故意不支持该脚本。此配置由 cargo-gnaw 使用,后者会根据 Cargo.toml 文件生成 GN 规则。如需了解详情,请参阅 cargo-gnaw 的 README

  3. 检查更新后的 crate 的版本字符串是否已在 third_party/rust_crates/BUILD.gn 中正确更新,并根据需要手动调整。

    在本地提交更改后,请再次运行 fx update-rustc-third-party,并确保它成功完成且未产生任何更改。您可以运行 git status 来确认。

  4. 运行以下命令以执行构建测试:

      fx set core.x64 && fx build
  5. 检查更改,确认许可或依赖项是否发生了任何变化。如果有此类更改,您必须完成 OSRB 审批流程。 请按以下步骤申请 OSRB 批准:

    • 使用 Open Source Review Board (OSRB) 模板创建问题。
    • 在问题中,执行以下操作:

      • Owner(所有者)字段留空。
        • OSRB 团队会定期开会审核相关问题。请耐心等待大约一周的时间,我们会给您回复。
      • 指定要添加的所有 crate。添加要添加的 crate 以及运行 fx update-rustc-third-party 后识别出的依赖项 crate。
      • 如果源代码库中有任何文件在供应商化时未包含,请在向 OSRB 提交的问题中指明这些文件。例如,仅用于测试但在 crate 被供应商化时被排除的字体文件需要包含在 OSRB 问题中。
  6. 更新了经过修改的 crate 的 OWNERS 文件。如需详细了解如何更新 OWNERS 文件,请参阅 OWNERS 文件部分。

  7. 获得 OSRB 批准后,将更改上传到 Gerrit 以供审核。在更改中添加 OSRB 问题 ID 编号。

  8. 如果没有许可或依赖项更改,您可以直接上传更改以供审核,而无需经过 OSRB 审批流程。

添加新镜像

在积极为上游代码库做出贡献或维护 Fuchsia 代码库的长期分支时,使用完整的 Git 代码库(而不是 Cargo 的供应商工具)导入 crate 可能会很有用。虽然此方法很有用,但与默认流程相比,其开销非常大,因此应谨慎使用。

  1. fuchsia.googlesource.com 上请求添加镜像。
  2. 将镜像添加到 Rust 运行时的 Jiri 清单中。
  3. 将 crate 的补丁部分添加到工作区。
  4. 运行更新脚本。

导入 crate 中的部分文件

在某些情况下,您可能只希望导入 crate 中的部分文件。例如,外部代码库中可能包含与 Fuchsia 的许可要求不兼容的可选许可。下面是一个发生这种情况的 OSRB 审核示例

为此,您需要将 crate 的文件添加到 /third_party/rust_crates/forks

  1. 按照添加外部 crate 的说明操作。
  2. 运行 fx update-rustc-third-party 后,将 crate 的下载副本从 /third_party/rust_crates/vendor/<my_crate> 移至 /third_party/rust_crates/forks/<my_crate>
  3. 对导入的文件进行所需的更改。
  4. 将一行代码添加到 /third_party/rust_crates/Cargo.toml[patch.crates-io] 部分,以指向您的新 crate:

    [patch.crates-io]
    ...
    my_crate = { path = "forks/<my_crate>" }
    ...
    
  5. 重新运行 fx update-rustc-third-partyfx build

  6. 添加一个与其他 crate 的 README.fuchsia 格式匹配的 /third_party/rust_crates/forks/<my_crate>/README.fuchsia 文件。如需了解应包含的内容,请参阅 /third_party/rust_crates/forks/README.md

Unicode crate

如果项目需要导入新的外部 crate 来处理与 Unicode 和国际化相关的功能,请优先使用 UNIC 项目中的 crate(如果有)。

豁免的非 UNIC crate

以下非 UNIC crate 已供应商化,因此不受此限制:

  • unicode-bidi
  • unicode-normalization
  • unicode-segmentation
  • unicode-width
  • unicode-xid

标准化理由

与其他 crate 相比,UNIC crate 具有明显的优势:

  • UNIC crate 在单个代码库中开发,共享通用代码和单个版本方案。

    • 独立开发的 crate 不共享共同的发布时间表、版本方案,也不遵循任何特定版本的 Unicode 标准。
  • UNIC crate 是根据一组一致的 Unicode 数据文件生成的。

    • 每个独立 crate 都使用数据的任意版本和子集。例如,不同的 crate 可能会对是否分配了特定代码点、其属性是什么等做出不同的假设。
  • UNIC 项目旨在实现全面的功能覆盖,就像 Rust 的 ICU 一样。如果该项目取得成功,我们对不相关 Unicode crate 的依赖应该会随着时间的推移而减少。

OWNERS 文件

系统会为所有外部 Rust crate 维护 OWNERS 文件,以指明负责审核和更新这些 crate 的人员。这些文件是通过构建图元数据和显式替换文件的组合生成的。

update-rustc-third-party 工具会尽力使用其有限的数据更新这些文件,但可能会出错。update-3p-owners 工具可以直接从我们的构建图重新生成 OWNERS 文件,从而取得更好的效果。

运行该工具

该工具会发现哪些构建目标依赖于给定 crate,这意味着它需要在完成最大“厨房水槽”构建后获得元数据:

  1. 运行 fx set core.x64 --with //bundles/buildbot/core --with //bundles/kitchen_sink --with-host '//tools/gn_desc:install_gn_desc(//build/toolchain:host_x64)'
  2. 运行 fx update-3p-owners --rust-metadata <FUCHSIA_BUILD_DIR>/rustlang/3p-crates-metadata.json

手动更新 OWNERS

供应商第三方 crate 的 OWNERS 文件由两个主要来源构建而成:

  1. 依赖于第三方 Rust crate 的目标的 OWNERS 文件会导入到其依赖的 crate 的 OWNERS 中。例如,如果 src/lib/foo 等目标依赖于 bar crate,则 bar crate 的 OWNERS 文件将包含 src/lib/foo/OWNERS
  2. 依赖于其他第三方 Rust crate 的第三方 Rust crate 会将其依赖项的 OWNERS 文件导入到自己的 OWNERS 文件中。例如,如果 bar crate 依赖于 baz crate,则 bar crate 的 OWNERS 文件将包含 third_party/rust_crates/vendor/bar-1.0.0/OWNERS

对于现有 crate 的版本升级,通常只需将 include 语句更新为更新后的 crate 的最新版本即可。

添加替换项

有些 crate 的用户数量过多,无法依靠用户来维护(请参阅旁观者效应)。其他模块则实现了特定于某个领域(例如安全)的行为,我们希望由特定团队负责审核这些代码。

在这些情况下,请向 //third_party/owners.toml 添加一个条目,其中包含要引用的其他 OWNERS 文件的路径,然后重新运行该工具。这会将反向依赖项元数据所有权替换为被替换的路径。

更新频率

Rust on Fuchsia 团队的一名成员目前负责定期运行该工具。如需跟踪自动更新 OWNERS 文件的流程,请参阅 https://fxbug.dev/42152910

在本地覆盖

如果您要向上游贡献代码,并希望运行树内 build 或测试,则覆盖第三方 crate 会很有用。您可以按照以下步骤实现此目的。

  1. third_party/rust_crates/forks/<my_crate> 下克隆(或符号链接)上游代码库。
  2. 将替换项添加到 third_party/rust_crates/Cargo.toml 中的 [patch.crates-io] 部分。
[patch.crates-io]
my_crate = { path = "forks/<my_crate>" }
  1. 您必须确保 crate 的 Cargo.toml 下的版本与 third_party/rust_crates/Cargo.toml 中对该 crate 的所有引用一致。
  2. 运行 fx update-rustc-third-party

问题排查

配置损坏

如果您在运行 fx update-rustc-third-party 后遇到如下错误:

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

您可以通过在 .cargo/config 中注释掉 Fuchsia 目标来解决此问题:

[build]
...
target = "x86_64-unknown-fuchsia"

添加注释后,它会变成:

[build]
...
# target = "x86_64-unknown-fuchsia"

我们正在上游跟踪此问题。