Fuchsia 构建系统

概述

Fuchsia 构建系统旨在为各种设备构建引导映像和可更新的软件包。 为此,它使用 GN,这是一种元构建系统(meta-build system),该系统生成构建文件供 Ninja 使用,而 Ninja 执行实际的构建。

注意,Zircon 使用不同的构建系统,尽管也使用了 GN 和 Ninja。

准备开始

如果您对 Fuchsia 的构建系统和 GN 不熟悉,请参阅使用 GN 构建,该文章概述了 GN 构建系统的基本原则。

板型和产品

生成镜像的内容由一组板型(board)和产品(product)控制,它们是 Fuchsia 构建的最小起始配置。板型和产品定义了依赖集合,其中定义了镜像中有哪些包(package)被包括在内、更新和包仓库。板型和产品记录了这些构建配置的结构和使用方法。

套装

套装(bundle)是源工作区一部分中相关包的分组,例如用于所有测试的所有工具。套装中提供了对于套装的概述。一组顶层套装定义在//bundles中。

构建目标

构建目标定义在分散于源工作区各处的 BUILD.gn 文件中。这些文件使用一种类 Python 语法来声明可构建对象:

  1. import("//build/some/template.gni")
  2. my_template("foo") {
  3. name = "foo"
  4. extra_options = "//my/foo/options"
  5. deps = [
  6. "//some/random/framework",
  7. "//some/other/random/framework",
  8. ]
  9. }

可用命令(使用 gn cli 工具调用)和结构(内置目标声明类型)定义在 GN 参考手册中。//build 项目里的 .gni 文件中也有许多自定义模板。

这些自定义模板大都定义了自定义目标声明类型,例如包声明类型。

TODO(pylaligand): list available templates

执行构建

执行构建的最简单方式就是通过 fx 工具,同 fx 工作流所描述的一样。继续阅读以理解 fx 暗中的操作。

文章的剩余部分假设 gnninja 命令在您的 PATH 中是可用的。这些命令可分别在 prebuilt/third_party/gn/<platform>prebuilt/third_party/ninja/<platform> 中找到。或者,如果您不想修改您的 PATH,您可以在所有调用前加上 fx,即 fx gnfx ninja

生成步骤

首先通过选择板型和产品配置基本构建产物:

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

这将会创建一个包含 Ninja 文件的构建目录(通常为 out/default

等价的 fx set 命令是:

  1. fx set core.x64

对于包含所有 GN 构建参数的列表,运行:

  1. fx gn args $(fx get-build-dir) --list

要获取关于 select_variant 参数的文档,请参阅变体

构建步骤

下一步是使用 Ninja 运行实际构建:

  1. fx ninja -C $(fx get-build-dir)

这就是 fx build 在暗中运行的内容。

重构建

要在修改源之后重构建工作区,只需重新执行构建步骤。即使您修改了 BUILD.gn 文件,这也是可行的,因为如果构建文件发生改动,那么 GN 会添加 Ninja 目标以更新 Ninja 目标!对于其他用于配置构建的文件也是如此。任何需要手动重新调用生成步骤的源的改动都是构建的程序错误,应当报告。

技巧和诀窍

检查 GN 目标的内容

  1. fx gn desc $(fx get-build-dir) //path/to/my:target

寻找对 GN 目标的引用

  1. fx gn refs $(fx get-build-dir) //path/to/my:target

为构建主机引用目标

许多主机工具(一些用于构建本身)需要随着最终镜像一同构建。

要为主机工具链从模块文件中引用构建目标:

  1. //path/to/target(//build/toolchain:host_x64)

要为主机工具链从 BUILD.gn 文件中引用构建目标:

  1. //path/to/target($host_toolchain)

仅构建某一特定目标

如果目标在 GN 构建文件中定义为 //foo/bar/blah:dash,该目标(及其依赖)可以使用下面的方式构建:

  1. fx ninja -C $(fx get-build-dir) -j64 foo/bar/blah:dash

注意,这仅对默认工具链中的目标运作。

注意:构建包目标不会导致包仓库更新,因为包仓库由 updates 组目标更新。要使更新的包改动通过 fx serve 可用,用户必须构建 updates 组。

浏览 Ninja 目标

GN 全面地记录了其生成的 Ninja 目标。文档可通过下面的方式访问:

  1. fx gn help ninja_rules

您也可以通过下面的方式浏览当前在您输出目录中定义的 Ninja 目标集合:

  1. fx ninja -C $(fx get-build-dir) -t browse

注意,Ninja 目标的存在并不意味着它会被构建——因为它要依赖于“默认”目标。

理解 Ninja 的所作所为和个中缘由

向您的 Ninja 命令添加 -d explain 以使其解释执行的每一个步骤。

调试构建用时问题

运行构建时,Ninja 记录日志,并生成可视化构建进程:

  1. 删除您的输出目录——这是为了确保日志仅反映您要将运行的构建迭代;
  2. 像您平时一样运行构建;
  3. 获取 https://github.com/nico/ninjatracing
  4. 运行 ninjatracing <output directory>/.ninja_log > trace.json
  5. 加载 json 结果文件至 Chrome 的 about:tracing

故障排除

我的 GN 目标未构建!

确保将其是模块文件中定义的标签,否则构建系统将忽略它。

GN 报告缺失 sysroot

您可能忘记了运行构建步骤的两条命令。

TODO(pylaligand): command showing path to default target

内部 GN 设置

TODO(pylaligand): .gn, default target, GN labels insertion