Fuchsia 构建系统
概述
Fuchsia 构建系统旨在为各种设备构建引导映像和可更新的软件包。 为此,它使用 GN,这是一种元构建系统(meta-build system),该系统生成构建文件供 Ninja 使用,而 Ninja 执行实际的构建。
注意,Zircon 使用不同的构建系统,尽管也使用了 GN 和 Ninja。
准备开始
如果您对 Fuchsia 的构建系统和 GN 不熟悉,请参阅使用 GN 构建,该文章概述了 GN 构建系统的基本原则。
板型和产品
生成镜像的内容由一组板型(board)和产品(product)控制,它们是 Fuchsia 构建的最小起始配置。板型和产品定义了依赖集合,其中定义了镜像中有哪些包(package)被包括在内、更新和包仓库。板型和产品记录了这些构建配置的结构和使用方法。
套装
套装(bundle)是源工作区一部分中相关包的分组,例如用于所有测试的所有工具。套装中提供了对于套装的概述。一组顶层套装定义在//bundles
中。
构建目标
构建目标定义在分散于源工作区各处的 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
文件中也有许多自定义模板。
这些自定义模板大都定义了自定义目标声明类型,例如包声明类型。
TODO(pylaligand): list available templates
执行构建
执行构建的最简单方式就是通过 fx
工具,同 fx 工作流所描述的一样。继续阅读以理解 fx
暗中的操作。
文章的剩余部分假设 gn
和 ninja
命令在您的 PATH
中是可用的。这些命令可分别在 prebuilt/third_party/gn/<platform>
和
prebuilt/third_party/ninja/<platform>
中找到。或者,如果您不想修改您的 PATH
,您可以在所有调用前加上 fx
,即 fx gn
或 fx ninja
。
生成步骤
首先通过选择板型和产品配置基本构建产物:
fx gn gen $(fx get-build-dir) --args='import("//boards/x64.gni") import("//products/core.gni")'
这将会创建一个包含 Ninja 文件的构建目录(通常为 out/default
)
等价的 fx set
命令是:
fx set core.x64
对于包含所有 GN 构建参数的列表,运行:
fx gn args $(fx get-build-dir) --list
要获取关于 select_variant
参数的文档,请参阅变体。
构建步骤
下一步是使用 Ninja 运行实际构建:
fx ninja -C $(fx get-build-dir)
这就是 fx build
在暗中运行的内容。
重构建
要在修改源之后重构建工作区,只需重新执行构建步骤。即使您修改了 BUILD.gn
文件,这也是可行的,因为如果构建文件发生改动,那么 GN 会添加 Ninja 目标以更新 Ninja 目标!对于其他用于配置构建的文件也是如此。任何需要手动重新调用生成步骤的源的改动都是构建的程序错误,应当报告。
技巧和诀窍
检查 GN 目标的内容
fx gn desc $(fx get-build-dir) //path/to/my:target
寻找对 GN 目标的引用
fx gn refs $(fx get-build-dir) //path/to/my:target
为构建主机引用目标
许多主机工具(一些用于构建本身)需要随着最终镜像一同构建。
要为主机工具链从模块文件中引用构建目标:
//path/to/target(//build/toolchain:host_x64)
要为主机工具链从 BUILD.gn
文件中引用构建目标:
//path/to/target($host_toolchain)
仅构建某一特定目标
如果目标在 GN 构建文件中定义为 //foo/bar/blah:dash
,该目标(及其依赖)可以使用下面的方式构建:
fx ninja -C $(fx get-build-dir) -j64 foo/bar/blah:dash
注意,这仅对默认工具链中的目标运作。
注意:构建包目标不会导致包仓库更新,因为包仓库由 updates
组目标更新。要使更新的包改动通过 fx serve
可用,用户必须构建 updates
组。
浏览 Ninja 目标
GN 全面地记录了其生成的 Ninja 目标。文档可通过下面的方式访问:
fx gn help ninja_rules
您也可以通过下面的方式浏览当前在您输出目录中定义的 Ninja 目标集合:
fx ninja -C $(fx get-build-dir) -t browse
注意,Ninja 目标的存在并不意味着它会被构建——因为它要依赖于“默认”目标。
理解 Ninja 的所作所为和个中缘由
向您的 Ninja 命令添加 -d explain
以使其解释执行的每一个步骤。
调试构建用时问题
运行构建时,Ninja 记录日志,并生成可视化构建进程:
- 删除您的输出目录——这是为了确保日志仅反映您要将运行的构建迭代;
- 像您平时一样运行构建;
- 获取 https://github.com/nico/ninjatracing;
- 运行
ninjatracing <output directory>/.ninja_log > trace.json
; - 加载 json 结果文件至 Chrome 的
about:tracing
。
故障排除
我的 GN 目标未构建!
确保将其是模块文件中定义的标签,否则构建系统将忽略它。
GN 报告缺失 sysroot
。
您可能忘记了运行构建步骤的两条命令。
TODO(pylaligand): command showing path to default target
内部 GN 设置
TODO(pylaligand): .gn, default target, GN labels insertion