本页面介绍了如何定义代码库规则,并提供了 。
外部代码库是一种目录树,
包含可在 Bazel build 中使用的源文件
运行其相应的代码库规则。代码库可以定义多种
但归根结底,每个仓库都通过调用 Repo 规则来定义,就像
build 目标通过调用 build 规则来定义。它们可以用来
第三方库(如 Maven 打包库),也可以生成
BUILD
文件(特定于运行 Bazel 的主机)。
仓库规则定义
在 .bzl
文件中,使用
repository_rule 函数来定义
新建代码库规则,并将其存储在全局变量中。定义代码库规则后
您可以将其调用为函数来定义代码库。这种调用通常是
从模块扩展实现内部执行
函数。
代码库规则定义的两个主要组成部分是其属性架构和 实现函数。属性架构决定了 传递给 Repo 规则调用,并且实现函数是 在需要提取代码库时运行
属性
属性是传递给 Repo 规则调用的参数。架构
使用 attrs
参数指定代码库规则所接受的属性,
代码库规则通过调用 repository_rule
来定义。定义一个
字符串形式的 url
和 sha256
属性:
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 工件。