Fuchsia 构建系统使用自定义 Ninja 二进制文件,可改进开发者体验。本页介绍了这些功能。
设计初衷
RFC-0153 详细介绍了为 Fuchsia 自定义 Ninja 的动机。
简而言之,有许多功能对 Fuchsia 开发者来说非常有用,但在源代码上游版本中很难获得。
所有特定于 Fuchsia 的更改都将在本地 Ninja git 镜像的本地 fuchsia-rfc-0153
分支上进行,并定期重新建立基准,以便轻松将其作为 GitHub 拉取请求发送到上游项目,如 RFC 的“策略”部分中所述。
功能:正在运行的命令的状态
将环境中的 NINJA_STATUS_MAX_COMMANDS
设置为一个严格正整数,以便在智能终端中运行时,Ninja 会在状态行下方输出一个表格,其中包含运行时间最长的命令及其经过的时间。例如,使用 export NINJA_STATUS_MAX_COMMANDS=4
时,状态可能如下所示:
[0/28477](260) STAMP host_x64/obj/tools/configc/configc_sdk_meta_generated_file.stamp
0.4s | STAMP obj/sdk/zircon_sysroot_meta_verify.stamp
0.4s | CXX obj/BUILD_DIR/fidling/gen/sdk/fidl/fuchsia.me...chsia.media/cpp/fuchsia.media_cpp_common.common_types.cc.o
0.4s | CXX obj/BUILD_DIR/fidling/gen/sdk/fidl/fuchsia.me...fuchsia.media/cpp/fuchsia.media_cpp.natural_messaging.cc.o
0.4s | CXX obj/BUILD_DIR/fidling/gen/sdk/fidl/fuchsia.me...dia/cpp/fuchsia.media_cpp_natural_types.natural_types.cc.o
下方动画图片展示了实际效果:
请注意:
在 Ninja 的模拟运行或详细调用(即使用
-n
或--verbose
标志)中,此功能会自动停用。当 Ninja 未在交互式 / 智能终端中运行时,此功能会自动停用。
运行控制台命令时,此功能也会暂停(在上述运行 Bazel 操作的示例中可见)。
借助此功能,您可以轻松直观地查看构建过程中的瓶颈,即导致其他命令无法并行运行的长时间运行的命令。
默认情况下,命令表每秒更新 10 次,这对于了解哪些耗时的命令会拖慢构建速度非常有用。您可以通过将 NINJA_STATUS_REFRESH_MILLIS
设置为以毫秒为单位的十进制值来更改刷新周期(请注意,系统会忽略低于 100 的值,因为经过的时间只会以小数点后一位的形式显示)。
功能:GNU Make Jobserver 支持
GNU Make Jobserver 协议允许构建系统限制任何时间点的并发作业(即线程或进程)总数,即使存在递归构建工具调用也是如此。
它需要顶级服务器设置一个由参与的客户端(例如编译器、链接器甚至构建工具)共享的作业槽池。
特定于 Fuchsia 的 Ninja 二进制文件既可以充当该协议的客户端,也可以充当服务器。
您可以在启动 Ninja 时通过 --jobserver
命令行标志启用服务器模式,也可以在环境中设置 NINJA_JOBSERVER=1
。
当 Ninja 启动时,系统会通过查看 MAKEFLAGS
环境变量的值来自动启用客户端模式。当从充当服务器的其他 build 调用 Ninja 时,这非常有用。
在 Fuchsia build 中,在 args.gn
中设置 enable_jobserver = true
可让顶级 Ninja 调用在服务器模式下启动。
例如,它已针对核心 IDK 和核心 SDK 构建器配置进行设置,可节省 6 到 12 分钟的构建时间。因为这些 build 需要从顶级 build 启动 24 个以上的 Ninja 子 build,这些 build 可以利用该协议更好地协调它们各自如何生成多个并行命令。
功能:持久模式可缩短启动时间
在环境中设置 NINJA_PERSISTENT_MODE=1
可加快连续调用 Ninja 的速度。此功能可让 Ninja 启动后台服务器进程来读取 build 清单一次,然后在连续 build 之间将 build 图表保留在内存中。
请注意:
此功能应完全透明,并且不应影响 Ninja 的行为。如果您发现问题或差异,请通过
fuchsia-build-team@google.com
与我们联系!系统会自动检测输入
.ninja
文件中的任何更改。在这种情况下,现有服务器将关闭,系统会自动启动新的服务器。更改 GN build 文件或执行jiri update
后,无需进行额外的用户互动。服务器进程会在空闲 5 分钟后正常关闭。在您的环境中设置
NINJA_PERSISTENT_TIMEOUT_SECONDS=<count>
以更改此延迟时间。使用
fx build -t server status
检索当前 build 目录的服务器状态。使用
fx build -t server stop
明确停止服务器的任何正在运行的实例。设置
NINJA_PERSISTENT_LOG_FILE=<path>
以将与持久模式相关的日志发送到给定文件路径。每个服务器进程目前会占用大约 1 GiB 的 RAM 来处理
core.x64
build 配置。具体数字取决于 Ninja 图的大小,而这又取决于您的args.gn
配置。每个 Ninja build 目录最多只能由一个服务器进程提供服务。但是,使用多个 build 目录时,可能会有多个进程。
Ninja 工具(例如
ninja -C <dir> -t commands <target>
)尚未在服务器上运行,因此仍会使用缓慢的启动方式。我们日后会修复此问题,以加快查询速度。
已知 bug / 注意事项,我们会加以解决:
目前,在同一目录中混合使用永久性 build 和非永久性 build 可能会使服务器感到困惑,因为系统无法正确检测对 Ninja build 和依赖项日志的独立更改。我们会解决此问题。
解决方法:在环境中取消设置
NINJA_PERSISTENT_MODE
之前,使用-t server stop
停止服务器。“快速启动”需要几秒钟的时间。目前,每个增量 build 仍需要对 build 图中的所有文件调用 stat(),这目前需要几秒钟的时间。我们日后会使用主机操作系统基于 inotify / kqueue 的文件系统监控功能来解决此问题,以便在仅修改了少数文件时立即启动。
不适用于 Windows(暂时不支持)。这是由于 Win32 存在技术限制,该限制会阻止将控制台句柄复制到其他进程。这对上游 Ninja 团队来说是一个主要问题,因为 Fuchsia 开发并非在 Windows 上进行。