GN 根目标

Fuchsia build 利用 GN 的新 root_patterns 功能大量 减小了 GN 和 Ninja 构建图的大小。这使得 gn gen 速度更快,Ninja 启动时间更短。

不过,此功能会更改 GN 在解析 BUILD.gn 文件时的默认行为 可能出人意料。本文介绍了具体操作方法。

GN 默认行为

由于历史原因,GN 将实例化 BUILD.gn 文件中定义的每个目标 在默认工具链环境中对后者进行评估时,即使 非常依赖它们

例如,请考虑以下三个 BUILD.gn 文件,它们分别定义两个目标: 之间有一些依赖关系:

 _//BUILD.gn____    _//foo/BUILD.gn__    _//bar/BUILD.gn_
|               |  |                 |  |                |
|   A           |  |         D -------------> E          |
|               |  |                 |  |                |
|      B --------------> C           |  |         F      |
|_______________|  |_________________|  |________________|

当 GN 解析此构建计划时,会发生以下情况:

  • GN 首先加载 //BUILD.gn 并对其进行评估。因为 则默认工具链会为 Cloud Storage 中的所有条目创建目标, 即 //:A//:B

  • GN 遵循其刚创建的目标的依赖项,因为 //:B 依赖于 //foo:C,它首先加载 //foo/BUILD.gn, 进行评估。

  • 由于它仍在默认工具链中,因此它会实例化所有 目标,从而创建 //foo:C//foo:D, 尽管后者不是 //:A//:B 的依赖项

  • 它再次遵循依赖项,并将加载 //bar/BUILD.gn, 评估并创建此处定义的所有目标,因此//bar:E//bar:F

这会导致最终的构建图包含比其他目标 但前提是 //BUILD.gn 表示 图表。

GN root_patterns

您可以更改此默认行为 .gn 文件中的 root_patterns, 或使用 --root-pattern=<pattern> 命令行选项(一次或 )。

这些参数定义了一个目标标签模式列表, 非依赖项目标,存在于评估的 BUILD.gn 文件中 默认工具链中。

例如,对同一 build 使用 gn gen --root-pattern=//:* 计划将通过以下方式改变 GN 的行为:

  • GN 首先加载 //BUILD.gn 并对其进行评估。因为这是 创建的文件中的任何目标 因为它们与模式匹配(//:* 实际上表示“任何目标 //BUILD.gn”)。因此,它会像之前一样创建 //:A//:B

  • GN 遵循依赖项,然后加载 //foo/BUILD.gn 并评估 。它会创建 //foo:C,因为这是 之前创建的其中一个定位条件但是,它不会 创建 //foo:D,因为它的标签与模式 //:* 不匹配。

  • GN 就到此为止,因为它没有创建 //foo:D,所以没有原因 以加载 //bar:BUILD.gn

因此,GN 会创建 3 个目标,而不是最终 build 图中的 6 个目标。

实际结果

在实践中,使用此功能可以减小 大幅缩短 gn gen 的时间。对于 使用 fx set minimal.x64 配置:

                        Default     --root-pattern=//:*    Reduction

Target count             183761              48375          -73%
Ninja files size (MiB)    571.7              180.2          -68%
`fx set` peak RAM (GiB)    5.02               2.89          -42%
`gn gen` time (s)          14.9               6.15          -58%
`fx set` time (s)          16.0               6.77          -57%

//:root_targets 目标。

//BUILD.gn 文件现在定义了一个名为 root_targets 的顶级目标 可用于将依赖项添加到 会包含在构建图中,即使没有任何其他操作依赖于它们。

在少数情况下,这一点至关重要:

  • 使用其输出的一些特殊 generated_file() 目标 作为隐式输入被其他目标使用,但无法依赖 。

  • 一些始终需要构建硬编码基础架构工具的目标 。

  • 一些构建器配置所需的一些目标 没有将它们列入universe_package_labels, 只是由于存在其他必要的目标而假定存在 定义同一个 BUILD.gn 文件。

向此列表添加的内容应最小化。总是最好能找到 来自其他任何顶级来源的真正传递依赖项 //BUILD.gn 目标,如果您确实需要始终保持 。