扩展程序概览

本页介绍了如何使用宏和规则扩展 BUILD 语言。

Bazel 扩展程序是以 .bzl 结尾的文件。使用 load 语句从扩展程序导入符号。

在学习更高级的概念之前,请先执行以下操作:

宏和规则

宏是实例化规则的函数。BUILD 文件变得过于重复或过于复杂时,宏非常有用,因为它可以让您重复使用一些代码。系统会在读取 BUILD 文件后立即对该函数进行求值。在对 BUILD 文件进行求值后,Bazel 几乎没有关于宏的信息:如果您的宏生成 genrule,Bazel 的行为就像您编写了 genrule 一样。因此,bazel query 将仅列出生成的 genrule

规则比宏更强大。它可以访问 Bazel 内部结构,并完全控制正在发生的事情。例如,它可以将信息传递给其他规则。

如果您想重复使用简单的逻辑,请先使用宏。如果宏变得复杂,最好将其设为规则。对新语言的支持通常通过规则完成。规则适用于高级用户,大多数用户永远不必编写规则;他们只会加载和调用现有规则。

求值模型

构建过程包含三个阶段。

  • 加载阶段 。首先,加载并求值构建所需的所有扩展程序和所有 BUILD 文件。BUILD 文件的执行只是实例化规则(每次调用规则时,都会将其添加到图中)。宏在此阶段进行求值。

  • 分析阶段 。系统会执行规则的代码(其 implementation 函数),并实例化操作。操作描述了如何从一组输入生成一组输出,例如“对 hello.c 运行 gcc 并获取 hello.o”。您必须在执行实际命令之前明确列出将生成哪些文件。换句话说,分析阶段会获取加载阶段生成的图,并生成操作图。

  • 执行阶段 。当需要至少一个操作的输出时,系统会执行这些操作。如果缺少文件或命令无法生成一个输出,构建就会失败。测试也会在此阶段运行。

Bazel 使用并行处理来读取、解析和求值 .bzl 文件和 BUILD 文件。每个文件在每次构建中最多读取一次,并且求值结果会被缓存并重复使用。只有在解析完文件的所有依赖项(load() 语句)后,才会对该文件进行求值。按照设计,加载 .bzl 文件没有明显的副作用,它只会定义值和函数。

Bazel 会尝试变得更智能:它使用依赖项分析来了解必须加载哪些文件、必须分析哪些规则以及必须执行哪些操作。例如,如果某条规则生成了当前构建不需要的操作,则不会执行这些操作。

创建扩展程序

编写自己的扩展程序时,以下两个链接非常有用。请将它们放在方便访问的位置:

进阶玩法

除了规则之外,您可能还需要编写 方面仓库规则