Fuchsia 构建系统旨在为各种设备构建启动映像和可更新的软件包。Fuchsia 构建系统使用 GN(一种元构建系统,用于生成由 Ninja 使用的构建文件,后者会执行实际的构建)。
注意:大多数开发者应通过
fx工作流(例如fx build和fx set)与构建系统互动,而不是直接运行 GN、Ninja 或 Bazel(即使是通过fx gn或fx ninja等封装容器)。
概念
如果您不熟悉 Fuchsia 的构建系统和 GN,请参阅使用 GN build,其中概述了 GN 构建系统的基本原理。
以下部分将介绍 Fuchsia 构建系统的一些概念。
build 配置
生成的 Fuchsia 映像的内容由 build 配置控制,而 build 配置是主板和产品的组合。主板和产品是 build 目标,用于定义映像中包含的软件包和依赖项。如需详细了解这些 build 配置的结构和用法,请参阅 build 配置。
编译目标
build 目标在整个源代码树中存在的 BUILD.gn 文件中定义。这些文件使用类似于 Python 的语法来声明可构建的对象。
例如:
import("//build/some/template.gni")
my_template("foo") {
name = "foo"
extra_options = "//my/foo/options"
deps = [
"//some/random/framework",
"//some/other/random/framework",
]
}
GN 参考中定义了可用的命令(通过 gn CLI 工具调用)和内置目标声明类型。//build 项目的 .gni 文件中还有一些自定义模板。
Fuchsia 定义了许多自定义模板,以支持定义和构建 Fuchsia 特定的制品。
构建优化标志
使用 fx set 构建 Fuchsia 时,您可以指定 build 优化标志来控制编译时间、运行时性能和可调试性之间的权衡。build 优化标志包括 --debug、--balanced 和 --release。
选择合适的标志可显著影响您的开发工作流、构建时间和生成的映像的性能特征。
快速比较
--debug |
--balanced |
--release |
|
|---|---|---|---|
| 主要关注点 | 调试断言,经过优化,可与调试程序搭配使用 | 编译速度快,运行时性能好。 | 最大限度提升运行时性能并尽可能缩小大小 |
| 编译时间 | 更快(增量) | 中等(对于某些目标平台,速度比发布版本快 2-4 倍) | 较慢 |
| 运行时性能 | 较慢 | 良好(适用于大多数开发场景) | 更快 |
| 二进制文件大小 | 变大 | 远小于调试版本,略大于发布版本 | 变小 |
| 优化 | 最小 | 部分 | 完整 |
| 调试体验 | 完整 | 介于 debug 和 release 之间(可调试性略低于调试) |
最小 |
| 推荐使用场景 | 主动编码和调试 | 每日开发和更快迭代 | 生产、基准比较、性能分析、最终验证 |
设置编译模式
将所需标志附加到 fx set 命令:
fx set PRODUCT.BOARD [--debug | --balanced | --release]
例如:
fx set core.x64 --debugfx set core.x64 --balanced
为什么选择 --balanced?
引入 --balanced 标志是为了解决 --release build 的编译时间开销过大的问题,尤其是对于大型 Rust 和 C++ 目标。通过有选择地启用优化并使用更快的替代方案(例如针对 C++ 使用 ThinLTO 而不是 Full LTO,针对 Rust 使用更多代码生成单元 [即编译时线程]),--balanced 可为需要优于调试性能的任务提供更好的开发者体验。
随着 Fuchsia 的发展,--release build 可能会纳入更激进(但编译速度可能更慢)的优化,例如 Rust Full LTO、PGO 和更高优化级别的性能关键型二进制文件。另一方面,如果您使用 --balanced,则可以进行性能感知型开发,从而受益于持续的编译时改进,同时保持良好的运行时特征。
build 优化标志的完整比较
本部分全面比较了以下构建优化标志:
--debug
- 主要目标:更快的增量编译速度,完全可调试。
- 优化:很少或没有。代码编译后尽可能接近源代码。
- 调试体验:包含完整的调试符号。
- 运行时性能:较慢。不适合用于性能测试或生产。
- 编译时间(完全重新构建):由于缺少优化传递,因此对于初始 build,通常比
--release和--balanced更快。 增量 build 通常是最快的。 - 适用情形:
- 积极开发和调试代码。
- 您需要使用调试器逐步执行代码并准确检查变量。
- 快速迭代比运行时性能更重要。
--balanced
- 主要目标:在编译速度和运行时性能之间取得平衡。
- 优化:一组精选的优化,可提供良好的运行时性能,而不会像
--release那样花费过多的编译时间。 - 调试体验:介于
--debug和--release之间,比发布版本略微更易于调试。某些优化可能会使精确调试比--debug更难。 - 运行时性能:良好。比完整的
--releasebuild 略慢(在某些方面可能慢 10-20%),但比--debug快得多。对于大多数开发和测试场景,性能通常可以接受。 - 编译时间:比
--release快得多。对于大型 Rust 目标,速度可以快 2-4 倍。- 例如:
netstack3的编译速度快了 4 倍(70 秒对比 280 秒)。 - 例如:
component_manager的编译速度快了 2.6 倍(70 秒对比 180 秒)。
- 例如:
- 适用情形:
- 如果您需要比
--debug更快的运行速度,但又想避免--release的漫长编译时间,则应将此模式设为默认编译模式。 - 一般开发和迭代,其中
--debug在运行时太慢。 - 当您需要测试性能合理的功能,但又不想等待完整发布版本时。
- 为了受益于持续的编译时改进,因为此模式正在积极优化速度。
- 如果您需要比
--release
- 主要目标:最大限度提高运行时性能并尽可能减小二进制文件大小。
- 优化:已启用全面优化。这包括以下激进技术:
- 链接时优化 (LTO),通常是完整 LTO。
- 配置文件引导的优化 (PGO)(如适用)。
- 更高的编译器优化级别(例如,
-O3)。
- 调试体验:极简。调试可能非常具有挑战性。
- 运行时性能:最快。此模式适用于基准测试和生产部署。
- 编译时间:最慢,因为需要进行广泛的优化传递和 LTO。
- 适用情形:
- 为生产或部署构建。
- 运行性能基准。
- 您需要尽可能小的二进制文件大小和尽可能高的运行时速度,并且愿意接受较长的构建时间。
执行 build
执行 build 的最简单方法是通过 fx 工具使用 fx set 来配置 build,然后使用 fx build,如 fx 工作流中所述。
配置 build
通过选择要构建的 board 和 product 来配置主要 build 工件:
fx 集
fx set core.x64您还可以在此命令中设置优化标志。请参阅build 优化标志。例如:
fx set core.x64 --balancedfx gn gen
fx gn gen $(fx get-build-dir) --args='import("//boards/x64.gni") import("//products/core.gni")'如需查看所有 GN build 实参的列表,请运行:
fx gn args $(fx get-build-dir) --list这会创建一个包含 Ninja 和 Bazel 文件的 build 目录(通常为 out/default)。
生成 build
使用 fx set 配置 build 制品后,您就可以构建 Fuchsia 了:
fx build
fx build这是 fx build 在底层运行的内容。
正在重新构建
如需在修改源代码后重新构建树,只需重新运行 fx build。如果您修改 BUILD.gn 文件,此规则也适用,因为 GN 会添加 Ninja 目标,以便在构建文件发生更改时更新 Ninja 目标。用于配置 build 的其他文件也是如此。
超全攻略
这些提示和技巧仅适用于使用 fx gn 命令。
检查 GN 目标的内容
fx gn desc $(fx get-build-dir) //path/to/my:target查找对 GN 目标的引用
fx gn refs $(fx get-build-dir) //path/to/my:target构建宿主的引用目标
各种主机工具(有些在 build 本身中使用)需要与最终映像一起构建。
如需从 BUILD.gn 文件中引用主机工具链的 build 目标,请执行以下操作:
//path/to/target($host_toolchain)
仅构建特定目标
如果目标在 GN build 文件中定义为 //foo/bar/blah:dash,则可以使用以下命令构建该目标(及其依赖项):
fx build
fx build //foo/bar/blah:dashfx build --host
fx build --host //foo/bar/blah:dash调试 build 时间问题
运行 build 时,Ninja 会保留可用于查看构建流程步骤的日志。如需分析特定 build 迭代的时序,请执行以下操作:
像往常一样运行 build。这会在输出目录中生成
.nina_log文件。使用
fx ninjatrace2json工具将 Ninja 日志转换为跟踪文件。例如:fx ninjatrace2json <your_output_directory>/.ninja_log > trace.json在兼容的跟踪记录查看器中加载生成的
trace.json文件。例如,在 Chrome 中,前往chrome://tracing并点击“加载”。
或者,您也可以使用 fx report-last-build。此命令会收集全面的 build 日志和时间信息。