本页面介绍了如何创建代码库规则,并提供了更多详情示例。
外部代码库是只能在 WORKSPACE
文件中使用的规则,并且会在 Bazel 的加载阶段启用非封闭操作。每条外部代码库规则都会创建自己的工作区,并拥有自己的 BUILD
文件和工件。它们可用于依赖于第三方库(例如 Maven 打包库),还可用于生成特定于运行 Bazel 的主机的 BUILD
文件。
创建代码库规则
在 .bzl
文件中,使用 repository_rule 函数创建新的代码库规则并将其存储在全局变量中。
自定义代码库规则的使用方式与原生代码库规则一样。它具有必需的 name
属性,并且其 build 文件中存在的每个目标都可以称为 @<name>//package:target
,其中 <name>
是 name
属性的值。
系统会在您明确构建规则,或者如果规则是构建的依赖项时加载该规则。在这种情况下,Bazel 将执行其 implementation
函数。此函数描述了如何创建代码库、其内容和 BUILD
文件。
属性
属性是规则参数,例如 url
或 sha256
。定义代码库规则时,您必须列出属性及其类型。
local_repository = repository_rule(
implementation=_impl,
local=True,
attrs={"path": attr.string(mandatory=True)})
如需访问属性,请使用 repository_ctx.attr.<attribute_name>
。
所有 repository_rule
都具有隐式定义的属性(就像构建规则一样)。两个隐式属性是 name
(就像构建规则一样)和 repo_mapping
。可通过 repository_ctx.name
访问代码库规则的名称。repo_mapping
的含义与原生代码库规则 local_repository
和 new_local_repository
的含义相同。
如果属性名称以 _
开头,则它是不公开的,用户无法设置。
实现职能
每条代码库规则都需要一个 implementation
函数。它包含规则的实际逻辑,并严格在加载阶段执行。
该函数只有一个输入参数 repository_ctx
。该函数会返回 None
表示在给定参数的情况下该规则是可重现的,或者会返回包含该规则的一组参数的字典,该字典会将该规则转变为生成相同代码库的可重现规则。例如,对于跟踪 Git 代码库的规则,该规则需要返回特定的提交标识符,而不是最初指定的浮动分支。
输入参数 repository_ctx
可用于访问属性值和非封闭函数(查找二进制文件、执行二进制文件、在代码库中创建文件或从互联网下载文件)。如需了解更多背景信息,请参阅库。例如:
def _impl(repository_ctx):
repository_ctx.symlink(repository_ctx.attr.path, "")
local_repository = repository_rule(
implementation=_impl,
...)
何时执行实现函数?
如果将代码库声明为 local
,则依赖关系图中的依赖项(包括 WORKSPACE
文件本身)发生变化会导致执行函数。
如果实现函数请求的依赖项缺失,实现函数可以重启。解决依赖项后,系统会重新执行实现函数的开头。为了避免不必要的重启(因为网络访问可能必须重复而代价高昂),系统会预提取标签参数,前提是所有标签参数都可以解析为现有文件。请注意,解析仅在函数执行期间构造的字符串或标签的路径仍可能会导致重启。
最后,对于非 local
代码库,只有以下依赖项的更改可能会导致重启:
- 定义代码库规则所需的
.bzl
文件。 - 在
WORKSPACE
文件中声明代码库规则。 - 使用
repository_rule
函数的environ
属性声明的任何环境变量的值。可以使用--action_env
标志从命令行强制执行这些环境变量的值(但此标志将使构建的每项操作失效)。 - 标签使用和引用的任何文件(例如,不是
mypkg/label.txt
,而是//mypkg:label.txt
)的内容。
强制重新提取外部代码库
有时,外部代码库可能会过时,而不更改其定义或依赖项。例如,代码库提取来源可能遵循第三方代码库的特定分支,并且该分支上提供新的提交。在这种情况下,您可以调用 bazel sync
,要求 bazel 无条件地重新提取所有外部代码库。
此外,某些规则会检查本地机器,如果本地机器升级,某些规则可能会过时。在这里,您可以要求 bazel 仅重新提取那些 repository_rule
定义中设置了 configure
属性的外部代码库,请使用 bazel sync --configure
。
示例
C++ 自动配置工具链:它使用代码库规则通过查找 C++ 编译器支持的本地 C++ 编译器、环境和标志,自动为 Bazel 创建 C++ 配置文件。
Go 代码库使用多个
repository_rule
来定义使用 Go 规则所需的依赖项列表。rules_jvm_external 默认创建一个名为
@maven
的外部代码库,为传递依赖项树中的每个 Maven 工件生成构建目标。