上次更新时间:2025 年 2 月 21 日
本页面面向在树内(即使用 fuchsia.git 检出)工作的 Fuchsia 开发者提供了与 Bazel 相关的重要指南。由于 Bazel 迁移是一个动态目标,因此本页面将经常更新,以反映重要更改。
摘要
自 2025 年第 1 季度起,请遵循以下准则:
如果您不执行产品组装,也不编写驱动程序软件包,请勿担心或开始在 Fuchsia 树中编写 Bazel 文件。
如果您要定义新的 product board 或输入 bundle,请使用 Bazel 目标和专用 Bazel SDK 规则进行定义,如此示例所示。
如果您编写的 Bazel 驱动程序软件包仅供 Bazel 定义的开发板使用,则应仅在 Bazel 中使用专用 Bazel SDK 规则定义它们,如此另一个示例所示。
所有新的开发板开发都应在 Bazel 中进行。如果开发板恰好依赖于现有的 GN 驱动程序软件包,请使用 bazel_driver_package() 模板将其公开到 Bazel 图(此处有示例)。
基于 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 atom 公开的平台内部库,请与 fuchsia-build-discuss@google.com 联系以说明您的用例。
理想情况下,添加新的不稳定 IDK atom 应该就足够了,但也可能存在例外情况,如下文的专门部分所述。
所有 Bazel 目标仍必须由 GN 目标封装,才能对构建后客户可见。
具体而言,一个或多个 Bazel 测试软件包必须由 GN
bazel_test_package_group()
目标定义封装,以确保fx test
和botanist
(我们的基础架构 CI 测试运行器工具)可以了解它们、按需构建它们并执行它们。从 GN/Ninja 操作调用 Bazel 的速度非常慢:即使 Bazel 决定不执行任何操作,也需要几秒钟的时间。一次只能运行一项。
这些操作由 GN 模板(例如
bazel_action
或其封装容器之一)定义,其实例使用//build/bazel:bazel_action_allowlist
目标进行控制。bazel_build_group()
或bazel_test_package_group()
等模板只会调用一次 Bazel,以便一起构建多个 Bazel 目标。这样可以实现更好的并行性。避免使用依赖于 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
的依赖项链会导致增量 build 速度明显变慢。由于在查看实际依赖项时缺乏清晰性,开发者体验也令人沮丧,并且构建失败可能变得更难理解和更难修复。
目前,最小链条如下所示:GN -> Bazel -> GN
,因为整个 build 由 GN 控制,而 build 后客户端只能查看 GN 专用目标定义,因此必须通过 GN 专用目标封装任何 Bazel 工件。
构建团队正在积极努力,让 Bazel 目标能够原生显示,以避免出现最后一个 Bazel -> GN
边缘。
这需要修改构建后工具和脚本(例如 fx test
和许多其他工具),以便直接查看 Bazel 输出,并能够根据需要重新构建这些输出,而无需调用 Ninja。
将平台库公开为 SDK Atom
若要让目标在 @fuchsia_sdk
中显示,必须满足以下条件:
其类型必须与我们支持的 IDK 原子架构之一相匹配,这意味着:
- 无 Rust 源代码库。
- 没有 Go 源代码库。
它们必须在 GN 图中定义(目前不支持在 Bazel 中定义 SDK/IDK 原子)。
由于 GN / Bazel 边界存在限制,因此它们不能是
testonly = true
。它们不能具有条件依赖项。我们的 IDK 架构不支持它们,原因很充分。
源代码库不能依赖于非 SDK 库。所有传递依赖项也必须是 SDK 的一部分。
它们必须使用与 SDK 兼容的 GN 模板进行定义,例如:
sdk_source_set()
:适用于 C++ 源代码库。sdk_static_library()
:适用于预构建的静态 C++ 库。sdk_shared_library()
:适用于预构建的共享 C++ 库。- 设置了
sdk_category
的fidl()
:适用于 FIDL 定义文件。 zx_library()
与sdk_publishable = true
搭配使用:适用于还需要关联到内核、引导加载程序或userboot
程序的 C++ 源代码库。sdk_fuchsia_package()
:适用于预构建的 Fuchsia 软件包。
如果您的平台库无法遵循这些限制,请与 fuchsia-build-discuss@google.com 邮寄名单联系,讨论替代方案。替代方案可能包括双图表目标定义,需要在迁移的其余部分中进行跟踪。
文档历史记录
2025 年 2 月 21 日:初始版本