代码库规则

<ph type="x-smartling-placeholder"></ph> 报告问题 <ph type="x-smartling-placeholder"></ph> 查看来源 每晚 · 7.2 条 · 7.1敬上 · 7.0 · 6.5 · 6.4

本页面介绍了如何定义代码库规则,并提供了 。

外部代码库是一种目录树, 包含可在 Bazel build 中使用的源文件 运行其相应的代码库规则。代码库可以定义多种 但归根结底,每个仓库都通过调用 repo 规则来定义,就像 build 目标通过调用 build 规则来定义。它们可以用来 第三方库(如 Maven 打包库),也可以生成 BUILD 文件(特定于运行 Bazel 的主机)。

仓库规则定义

.bzl 文件中,使用 repository_rule 函数来定义 新建代码库规则,并将其存储在全局变量中。定义代码库规则后 您可以将其调用为函数来定义代码库。这种调用通常是 从模块扩展实现内部执行 函数。

代码库规则定义的两个主要组成部分是其属性架构和 实现函数。属性架构决定了 传递给 Repo 规则调用,并且实现函数是 在需要提取代码库时运行

属性

属性是传递给 Repo 规则调用的参数。架构 使用 attrs 参数指定代码库规则所接受的属性, 代码库规则通过调用 repository_rule 来定义。定义一个 字符串形式的 urlsha256 属性:

http_archive = repository_rule(
    implementation=_impl,
    attrs={
        "url": attr.string(mandatory=True),
        "sha256": attr.string(mandatory=True),
    }
)

要访问实现函数中的某个属性,请使用 repository_ctx.attr.<attribute_name>

def _impl(repository_ctx):
    url = repository_ctx.attr.url
    checksum = repository_ctx.attr.sha256

所有 repository_rule 都具有隐式定义的属性 name。这是一个 字符串属性,其行为方式有点神奇:当被指定为 代码库规则调用,需要一个明显的代码库名称;但当您从 repo 规则的实现函数使用 repository_ctx.attr.name,则它会返回 规范代码库名称

实现函数

每条代码库规则都需要一个 implementation 函数。它包含 规则的实际逻辑,并严格在加载阶段执行。

该函数只有一个输入参数 repository_ctx。函数 会返回 None,这表示在给定给定条件的情况下,规则可重现。 或包含该规则的一组参数的字典 会将该规则变为可重现的规则,从而生成相同的代码库。对于 例如,对于跟踪 git 代码库的规则,这意味着 指定的提交标识符,而不是最初作为浮动分支的 。

输入参数 repository_ctx 可用于 访问属性值和非封闭函数(查找二进制文件、 执行二进制文件、在代码库中创建文件或下载文件 来自互联网)。请参阅 API 文档 更多背景信息。示例:

def _impl(repository_ctx):
  repository_ctx.symlink(repository_ctx.attr.path, "")

local_repository = repository_rule(
    implementation=_impl,
    ...)

何时执行实现函数?

当 Bazel 需要 目标,例如当另一个目标(在另一个 repo)依赖于它,或者它是否在命令行中提及。通过 实现函数需要在文件中创建代码库 系统。此过程称为“提取”代码库

与常规目标不同,在执行下列操作时 导致代码库与众不同的更改。这是 因为 Bazel 要么无法检测到对某些方面所做的更改 每次构建都会耗费过多开销(例如,提取的内容 )。因此,仅当出现以下任一情况时,系统才会重新提取 会发生以下变化:

  • 传递给 Repo 规则调用的属性。
  • 构成 Repo 规则实现的 Starlark 代码。
  • 传递给 repository_ctx 的任何环境变量的值 getenv() 方法,或使用environ repository_rule。值 您可以使用 --repo_env 标志。
  • 传递给 read()execute() 等方法的任何文件的内容 repository_ctx 的方法,该方法由标签引用(例如, //mypkg:label.txt,但不包括 mypkg/label.txt
  • 执行 bazel fetch --force 时。

repository_rule 的两个参数用于控制代码库 :

  • 如果设置了 configure 标志,系统仅会在以下时间重新提取仓库: bazel fetch(如果--configure参数传递给它时(如果 属性未设置,则此命令不会导致重新提取)
  • 如果设置了 local 标志,则除了上述情况之外,代码库还会 在 Bazel 服务器重启时进行重新提取

重启实现函数

创建代码库时,可以重启实现函数 如果其请求的依赖项缺失,则获取。在这种情况下, 实现函数将停止,缺少的依赖项会被解析, 依赖项解决后,系统将重新执行该函数。接收者 避免不必要的重启(重启成本高昂,因为网络访问 标签参数会被预提取,前提是 标签参数可解析为现有文件。请注意,解析 仅在执行期间构造的字符串或标签的路径 也仍可能导致重启。

强制重新提取外部代码库

有时,在未对外部代码库进行任何更改的情况下, 定义或依赖项。例如,提取来源的代码库可能 跟踪第三方代码库的特定分支,并且新提交会 该分支提供的所有资源这种情况下,您可以让 bazel 重新获取 外部代码库。bazel fetch --force --all

此外,有些代码库规则会检查本地机器, 如果本地计算机升级,则会过时。在这里,你可以要求 Bazel 只会重新提取 repository_rule 设置了 configure 属性,请使用 bazel fetch --all --configure

示例

  • C++ 自动配置的工具链: 它使用代码库规则自动创建 为 Bazel 创建 C++ 配置文件,方法是查找本地 C++ 编译器 环境和 C++ 编译器支持的标志。

  • Go 代码库 使用多个 repository_rule 定义依赖项列表 使用 Go 规则所需的操作。

  • rules_jvm_external 用于创建 默认名为 @maven 的外部代码库,用于生成构建目标 传递依赖项树中的每个 Maven 工件。