上次更新时间:2025-03-06
本页面为在源代码树中(即使用 fuchsia.git 代码库)工作的 Fuchsia 开发者提供了重要的 Bazel 相关指南。由于 Bazel 迁移是一个不断变化的目标,因此我们会经常更新本页面,以反映重要变更。
摘要
自 2025 年第 1 季度起,需遵循以下准则:
如果您不执行产品组装,也不编写驱动程序软件包,则无需担心或开始在 Fuchsia 树中编写 Bazel 文件。
如果您要定义新的产品主板或输入软件包,请使用 Bazel 目标和专用 Bazel SDK 规则来完成,如此示例所示。
如果您编写的 Bazel 驱动程序软件包仅供 Bazel 定义的板使用,请仅在 Bazel 中使用专用 Bazel SDK 规则定义它们,如此其他示例所示。
所有新的主板开发都应在 Bazel 中进行。如果您的主板恰好依赖于现有的 GN 驱动程序软件包,请先通过在其 GN
fuchsia_driver_package()定义中设置export_to_bazel = true实参,将其公开给 Bazel 图,然后创建一个引用 GN 软件包制品 (此处有示例,此处有示例) 的 Bazelfuchsia_prebuilt_package() 同伴目标定义。基于 Bazel 的驱动程序软件包只能依赖于通过
@fuchsia_sdk和@internal_sdk代码库公开的平台库。@fuchsia_sdk包含一组以 OOT 方式分发的库,但确实包含供驱动程序开发者使用的“不稳定”平台库(请在上一链接的行中查找(unstable)标记)。例如,
@fuchsia_sdk//pkg:driver_power_cpp会公开来自 GN//sdk/lib/driver/power/cpp库定义的库。@internal_sdk包含类似的定义,但仅适用于仅在树内 Fuchsia build 中可用的 SDK atom,因此可能更加不稳定。不过,我们计划将其移除,转而将所有不稳定原子移至@fuchsia_sdk,因此不应再向其中添加任何原子。请勿为内部平台库编写 BUILD.bazel 文件。
目前,应避免为同一非 SDK 库重复定义 BUILD.gn / BUILD.bazel。
如果您的驱动程序需要使用尚未作为不稳定 IDK 原子公开的平台内部库,请联系 fuchsia-build-discuss@google.com 来介绍您的使用情形。
理想情况下,添加新的不稳定 IDK atom 应该就足够了,但可能会有例外情况,如下文专用部分中所述。
所有 Bazel 目标都必须仍然由 GN 目标封装,才能对 build 后客户端可见。
具体而言,一个或多个 Bazel 测试软件包必须由 GN
bazel_test_package_group()目标定义封装,以确保fx test和botanist(我们的基础设施 CI 测试运行程序工具)能够了解这些软件包、按需构建它们并执行它们。从 GN/Ninja 操作调用 Bazel 的速度非常慢:即使 Bazel 决定不执行任何操作,也需要花费几秒钟的时间。Ninja 会将它们分批处理,并以组的形式运行所有等待中的可运行 Bazel 操作。
这些操作由 GN 模板(例如
bazel_action或其封装容器之一)定义。避免依赖于 Bazel 制品的非终端 GN 目标
由于跨越 GN/Bazel 边界的成本很高,因此形如
GN -> Bazel -> GN -> Bazel -> GN的依赖链会导致增量 build 的速度明显变慢,必须避免。如需了解详情,请参阅下文中的专门部分。
双重 BUILD.bazel 和 BUILD.gn 定义
在迁移的剩余时间里,我们许多目标都将需要在等效的 BUILD.gn 和 BUILD.bazel 文件中进行双重定义。
如果存在此类双 build 文件,至关重要的是,必须确保这些文件始终保持同步。此外,还应跟踪两个图表中都存在的双重定义目标。
一种简单的方法是手动编写这些测试,并在两个文件中使用匹配的 LINT If-This-Then-That 代码块,以便在 CL 审核期间检测偏差。
更好的方法是使用最近推出的 bazel2gn 等工具,自动将 BUILD.bazel 转换为等效的 BUILD.gn。
目前,bazel2gn 仅为原型,仅处理 Go 目标。随着时间的推移,它会不断改进,以支持更多使用情形,但目前 Fuchsia 开发者不应使用它,其使用范围仅限于 Fuchsia Build 团队。
在这两种情况下,都会引入注释标记和相关工具,以跟踪哪些目标在两个图中都有双重定义。
GN 图与 Bazel 图之间的依赖关系
由于跨越 GN/Bazel 边界的成本很高,因此看起来像 GN -> Bazel -> GN -> Bazel -> GN 的依赖链会导致增量构建速度明显变慢。此外,由于在查看实际依赖项时不够清晰,开发者体验也会令人沮丧,并且构建失败会变得更难理解和修复。
目前,最小链看起来像 GN -> Bazel -> GN,因为整个 build 由 GN 控制,并且 build 后的客户端仅查看 GN 特定的目标定义,因此任何 Bazel 制品都必须通过 GN 特定的目标进行封装。
构建团队正积极努力,使 Bazel 目标原生可见,以避免出现最后一个 Bazel -> GN 边缘。
这需要修改 build 后工具和脚本(例如 fx test 和许多其他工具和脚本),以便直接查看 Bazel 输出,并能够在需要时重建这些输出,而无需调用 Ninja。
将平台库公开为 SDK atom
若要使目标在 @fuchsia_sdk 中可见,必须满足以下条件:
其类型必须与我们支持的某个 IDK Atom 架构相匹配,这意味着:
- 没有 Rust 源代码库。
- 没有 Go 源代码库。
它们必须在 GN 图中定义(目前不支持在 Bazel 中定义 SDK/IDK atom)。
由于 GN / Bazel 边界存在限制,它们无法为
testonly = true。它们不能有条件依赖项。我们的 IDK 架构不支持这些功能,这是有充分理由的。
源库不能依赖于非 SDK 库。它们的所有传递依赖项也必须是 SDK 的一部分。
它们必须使用与 SDK 兼容的 GN 模板进行定义,例如:
sdk_source_set():适用于 C++ 源库。sdk_static_library():适用于预构建的静态 C++ 库。sdk_shared_library():适用于预构建的共享 C++ 库。- 将
fidl()设置为sdk_category:适用于 FIDL 定义文件。 zx_library(),并将sdk_publishable设置为 SDK 类别:对于还需要链接到内核、引导加载程序或userboot程序的 C++ 源代码、静态库和共享库。sdk_fuchsia_package():适用于预构建的 Fuchsia 软件包。
如果您的平台库无法遵循这些限制,请与 fuchsia-build-discuss@google.com 邮件列表联系,讨论替代方案。替代方案可能包括双图目标定义,需要在迁移的剩余阶段进行跟踪。
文档历史记录
2025-03-06:修复了有关如何将 Bazel 软件包导出到 GN 的示例。 2025-02-21:初始版本