关于覆盖外部存储库的文档含糊不清,但https://docs.bazel.build/versions/2.2.0/external.html可能是最好的参考。
我的理解是:
WORKSPACE
在被调用的函数中或函数中声明的存储库WORKSPACE
被延迟评估。这很重要,因为评估存储库规则可能非常昂贵(它们往往会下载大文件)并且对于很多构建来说可能不是必需的。
- 使用相同名称多次声明存储库不是错误。如果尚未评估存储库规则,则将使用最后的声明。
- 当存储库中的任何标签被解析时,将评估存储库规则。这包括:
- 使用语句加载
.bzl
文件。load
- 将属性中的标签传递给另一个被评估的存储库规则。
ctx.path
在另一个被评估的存储库规则中的标签上使用。
- (
WORKSPACE
完全解决之后)构建一个加载某些内容或依赖于存储库中某些内容的目标。
- 评估存储库规则后,不能再覆盖它。稍后声明的同名存储库将被静默忽略。
这种逻辑令人困惑,当一个规则被多次声明时,很难理解使用的是什么版本的东西。
- 理想情况下,每条规则都应该声明一次,
WORKSPACE
以尽量减少混淆。当然,如果您的依赖项提供了声明传递依赖项的函数,这可能会很困难。在某些情况下,您最终可能会手动内联这些函数。
- 像这样的依赖函数
go_rules_dependencies
应该避免覆盖使用这样的函数声明的任何内容_maybe
:
def _maybe(repo_rule, name, **kwargs):
if name not in native.existing_rules():
repo_rule(name = name, **kwargs)
- 安排您的
WORKSPACE
文件以确保直接依赖关系已声明并可能更早解决。这可能会使相关声明更难分组,但评估语义会更清晰。
http_archive
以及git_repository
规则集和直接依赖项的存储库。
load
存储库规则和依赖函数的语句。
- 其他直接依赖项(例如
go_repository
)。
- 调用传递依赖的依赖函数。
- 工具链注册。
对于调试,该native.existing_rules
功能非常方便。它返回到目前为止声明的所有存储库的列表,以及声明它们的属性。定义一个调用它并打印结果的函数,然后从WORKSPACE
.