构建系统概述

本文档概述了构建系统的工作原理。它面向希望了解构建系统内部机制的人员。它不适用于那些偶尔与构建系统交互的人员。话虽如此,知识赋予力量,因此请继续阅读。

构建系统由许多不同的组件组成,它们协同工作以构建源代码树。我们从图形概述开始。

digraph build_components {
   rankdir="LR";
   "configure" -> "config.status" -> "build backend" -> "build output"
}

阶段 1:配置

阶段 1 主要围绕 configure 脚本展开,该脚本是一个 bash shell 脚本。该文件是从名为 configure.in 的文件生成的,该文件是用 M4 编写的,并使用 Autoconf 2.13 处理以创建最终的 configure 脚本。您无需担心如何获取 configure 文件:构建系统会为您完成此操作。

configure 的主要工作是确定系统和编译器的特性,应用传递给它的选项,并验证一切看起来都适合构建。 configure 的主要输出是对象目录中名为 config.status 的可执行文件。 configure 还生成一些其他文件(例如 autoconf.mk)。但是,就体系结构而言,最重要的文件是 config.status

config.status 文件的存在可能对那些以前使用过 Autoconf 的人来说很熟悉。但是,Mozilla 的 config.status 与您见过的几乎任何其他 config.status 都不一样:它是用 Python 编写的!我们没有让 configure 脚本生成 shell 脚本,而是让它生成 Python。

现在是时候提到 Python 在我们的构建系统中很普遍了。如果我们需要为构建系统编写代码,我们会用 Python 来做。这就是我们的做事方式。更多信息,请参见 Python 和构建系统

config.status 包含两部分:表示 configure 输出的数据结构,以及用于准备/配置/生成适当构建后端的命令行界面。(构建后端仅仅是用于构建树的工具,例如 GNU Make 或 Tup)。这些数据结构基本上描述了系统的当前状态以及现有构建配置的外观。例如,它定义了要使用的编译器、如何调用它、启用了哪些应用程序功能等。建议您打开 config.status 自己查看一下!

一旦我们生成了 config.status 文件,我们就进入阶段 2。

阶段 2:构建后端准备和构建定义

一旦 configure 确定了当前的构建配置,我们就需要将其应用于源代码树,以便我们能够实际构建。

本质上发生的事情是,自动生成的 config.status Python 脚本会在 configure 生成它后立即执行。 config.status 负责告诉工具如何构建树。为此, config.status 必须首先扫描构建系统定义。

构建系统定义由树中的各种 moz.build 文件组成。每个目录或一组相关目录大约有一个 moz.build 文件。每个 moz.build 文件定义其构建配置部分的工作方式。例如,它会说“我希望编译这些 C++ 文件”或“在这些目录中查找其他信息”。config.status 从根目录的 moz.build 文件开始,然后通过遵循 DIRS 变量或类似变量向下进入引用的 moz.build 文件。

在读取 moz.build 文件时,会发出描述整体构建系统定义的数据结构。然后,这些数据结构被馈送到构建后端,构建后端执行诸如写入要由构建工具读取的文件之类的操作。例如,make 后端将写入 Makefile

config.status 运行时,您将看到以下输出

Reticulating splines...
Finished reading 1096 moz.build files into 1276 descriptors in 2.40s
Backend executed in 2.39s
2188 total backend files. 0 created; 1 updated; 2187 unchanged
Total wall time: 5.03s; CPU time: 3.79s; Efficiency: 75%

这意味着总共读取了 *1096* 个 moz.build 文件。总共从它们派生出了 *1276* 个描述构建配置的数据结构。仅读取这些文件并生成数据结构就花费了 *2.40s* 的墙上时间。 *1276* 个数据结构被馈送到构建后端,然后构建后端确定它必须管理从这些数据结构派生的 *2188* 个文件。其中大多数文件已经存在并且不需要更改。但是,由于新配置,有 *1* 个文件被更新。整个过程花费了 *5.03s*。尽管如此,只有 *3.79s* 是 CPU 时间。这可能意味着我们大约花费了 *25%* 的时间等待 I/O。

有关 moz.build 文件工作原理的更多信息,请参见 moz.build 文件

阶段 3:调用构建后端

当大多数人想到构建系统时,他们会想到阶段 3。在这里,我们获取树中的所有代码并生成 Firefox 或您正在创建的任何应用程序。阶段 3 有效地获取阶段 2 生成的一切并运行它。自 Mozilla 诞生以来,这一直是 make 使用 Makefile 的过程。但是,随着 moz.build 文件的过渡,您可能会很快看到非 Make 构建后端,例如 Tup 或 Visual Studio。

在构建树时,大部分时间都花在阶段 3 上。这是安装头文件、编译 C++ 文件、预处理文件等的时间。