扩展程序概览

报告问题 查看源代码 每夜版 · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

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

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

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

宏和规则

宏是实例化规则的函数。宏分为两种类型:符号宏(Bazel 8 中的新功能)和旧版宏。这两种宏的定义方式不同,但从用户的角度来看,它们的行为几乎相同。当 BUILD 文件过于重复或过于复杂时,宏非常有用,因为它可以让您重复使用一些代码。系统会在读取 BUILD 文件后立即对该函数求值。在评估 BUILD 文件后,Bazel 几乎没有关于宏的信息。如果您的宏生成 genrule,Bazel 的行为将几乎与您在 BUILD 文件中声明该 genrule 的行为相同。(唯一的例外情况是,在符号宏中声明的目标具有特殊的可见性语义:符号宏可以向软件包的其余部分隐藏其内部目标。)

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

如果您想重复使用简单逻辑,请从宏开始;我们建议使用符号宏,除非您需要支持旧版 Bazel。如果宏变得复杂,最好将其设为规则。支持新语言通常通过规则来实现。规则适用于高级用户,大多数用户永远都不需要编写规则,只需加载和调用现有规则即可。

评估模型

一次 build 包含三个阶段。

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

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

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

Bazel 使用并行处理来读取、解析和评估 .bzl 文件和 BUILD 文件。每个 build 最多读取一次文件,评估结果会被缓存并重复使用。只有在文件中的所有依赖项(load() 语句)都已解析后,才会对该文件进行评估。根据设计,加载 .bzl 文件不会产生明显的副作用,它只会定义值和函数。

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

创建扩展程序

在编写自己的扩展程序时,以下两个链接会非常有用。让它们触手可及:

进一步了解

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