Fuchsia 构建系统

Fuchsia 构建系统旨在为各种设备构建启动映像和可更新软件包。Fuchsia 构建系统使用 GN,这是一个元构建系统,用于生成供 Ninja 使用的构建文件,后者会执行实际构建。

概念

如果您不熟悉 Fuchsia 的构建系统和 GN,请参阅使用 GN build,其中概述了 GN build 系统的基本原理。

以下部分介绍了 Fuchsia 构建系统的几个概念。

面板和产品

生成的 Fuchsia 映像的内容由开发板和产品共同控制。开发板和产品是构建目标,用于定义映像中包含的软件包和依赖项。如需详细了解这些 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 cli 工具调用)和内置目标声明类型的构造函数在 GN 参考文档中定义。//build 项目中的 .gni 文件中还包含一些自定义模板。

Fuchsia 定义了许多自定义模板,以支持定义和构建 Fuchsia 专用工件。

build 优化标志

使用 fx set 构建 Fuchsia 时,您可以指定 build 优化标志,以控制编译时间、运行时性能和可调试性之间的权衡。build 优化标志为 --debug--balanced--release

选择正确的标志可能会显著影响开发工作流、构建时间和生成映像的性能特性。

快速比较

--debug --balanced --release
主要焦点 调试断言,经过优化,可与调试程序搭配使用 编译速度和良好的运行时性能。 最高运行时性能和最小尺寸
编译时间 更快(增量) 中等(对于某些目标平台,比正式版快 2-4 倍) 减速
运行时性能 减速 良好(适用于大多数开发场景) 更快
二进制文件大小 较大 比调试版本小得多,比发布版本大一点 较小
优化 最小 部分 完整
调试体验 完整 介于 debugrelease 之间(调试能力略低于调试模式) 最小
推荐使用场景 主动编码和调试 每日开发和更快的迭代 生产、基准测试、最终验证

设置编译模式

将所需的标志附加到 fx set 命令:

fx set PRODUCT.BOARD [--debug | --balanced | --release]

例如:

  • fx set core.x64 --debug
  • fx set core.x64 --balanced

为什么选择 --balanced

--balanced 标志旨在解决 --release build 的大量编译时间开销问题,尤其是对于大型 Rust 和 C++ 目标。通过选择性启用优化,并针对 C++ 使用 ThinLTO(而非 Full LTO)等更快的替代方案,以及针对 Rust 使用更多 codegen 单元(即编译时线程),--balanced 可为需要比调试性能更好的任务提供更好的开发者体验。

随着 Fuchsia 的不断演进,--release build 可能会纳入更激进(编译速度可能会更慢)的优化,例如 Rust Full LTO、PGO,以及针对对性能至关重要的二进制文件的更高优化级别。另一方面,如果您使用 --balanced,则可以进行注重性能的开发,从而受益于持续的编译时间改进,同时保持良好的运行时特性。

build 优化标志的完整比较

本部分将对以下 build 优化标志进行全面比较:

--debug
  • 主要目标:更快的增量编译速度、完全可调试。
  • 优化:几乎没有优化。编译后的代码尽可能接近源代码。
  • 调试体验:包含完整的调试符号。
  • 运行时性能:较慢。不适用于性能测试或生产环境。
  • 编译时间(完全重新构建):对于初始 build,由于缺少优化传递,通常比 --release--balanced 更快。增量 build 通常速度最快。
  • 适用情形
    • 积极开发和调试代码。
    • 您需要使用调试程序逐行调试代码并准确检查变量。
    • 快速迭代比运行时性能更重要。
--balanced
  • 主要目标:在编译速度和运行时性能之间取得平衡。
  • 优化:一组精选的优化,可在不增加 --release 的编译时间的情况下提供良好的运行时性能。
  • 调试体验--debug--release 的调试能力略高于发布版本。某些优化可能会使精确调试比 --debug 更难。
  • 运行时性能:良好。比完整的 --release build 稍慢(在某些方面可能慢 10-20%),但比 --debug 快得多。在大多数开发和测试场景中,性能通常是可接受的。
  • 编译时间:比 --release 快得多。对于大型 Rust 目标,速度可提高 2-4 倍
    • 例如:netstack3 的编译速度提高了 4 倍(70 秒对比 280 秒)。
    • 例如:component_manager 的编译速度提高了 2.6 倍(70 秒对比 180 秒)。
  • 适用情形
    • 如果您需要比 --debug 更快地运行某些内容,但又想避免 --release 的编译时间过长,则应将此模式作为默认编译模式。
    • 在运行时 --debug 运行缓慢的常规开发和迭代。
    • 当您需要测试具有合理性能的功能,而无需等待完整发布 build 时。
    • 此模式正在积极优化以提高速度,因此您可以受益于持续的编译时间改进。
--release
  • 主要目标:最大限度地提高运行时性能并缩减二进制文件大小。
  • 优化:已启用完整优化。这包括以下侵略性做法:
    • 链接时优化 (LTO),通常是完整 LTO。
    • 配置文件引导型优化 (PGO)(如果适用)。
    • 更高的编译器优化级别(例如 -O3)。
  • 调试体验:最低限度。调试可能非常具有挑战性。
  • 运行时性能:最快。这是用于基准测试和生产部署的模式。
  • 编译时间:最慢,因为需要进行大量优化传递和 LTO。
  • 适用情形
    • 构建正式版或部署。
    • 运行性能基准测试。
    • 您需要绝对最小的二进制文件大小和最高的运行时速度,并且愿意接受较长的构建时间。

执行 build

如需执行 build,最简单的方法是通过 fx 工具使用 fx set 配置 build,然后使用 fx build(如 fx 工作流中所述)。

配置 build

选择要构建的开发板和产品,配置主要 build 工件:

fx set

fx set core.x64

您还可以在此命令上设置优化标志。请参阅构建优化标志。例如:

fx set core.x64 --balanced

fx gn gen

fx gn gen $(fx get-build-dir) --args='import("//boards/x64.gni") import("//products/core.gni")'

如需查看所有 GN 构建参数的列表,请运行以下命令:

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 本身中使用)。

如需从 BUILD.gn 文件中引用主机工具链的 build 目标,请执行以下操作:

//path/to/target($host_toolchain)

仅构建特定目标

如果在 GN build 文件中将某个目标定义为 //foo/bar/blah:dash,则可以使用以下命令构建该目标及其依赖项:

fx build

fx build //foo/bar/blah:dash

fx build --host

fx build --host //foo/bar/blah:dash

调试构建时间问题

运行 build 时,Ninja 会保留日志,以便查看 build 流程的步骤。如需分析特定 build 迭代的时机,请执行以下操作:

  1. 像往常一样运行 build。这会在输出目录中生成 .nina_log 文件。

  2. 使用 fx ninjatrace2json 工具将 Ninja 日志转换为轨迹文件。例如:

    fx ninjatrace2json <your_output_directory>/.ninja_log > trace.json
    
  3. 在兼容的轨迹查看器中加载生成的 trace.json 文件。例如,在 Chrome 中,前往 chrome://tracing 并点击“加载”。

或者,您也可以使用 fx report-last-build。此命令会收集全面的 build 日志和时间信息。