2

我在使用 Bazel 构建 Go 项目时遇到了一个问题,发现它的根本原因是loadimport的顺序@io_bazel_rules_go

收到答案后,我参考了 Bazel 的官方文档,如果它是在规范中定义的,或者只是对实现的隐式依赖。我还不能检查所有官方文档,但听起来以下文档与这个问题相关,但load影响的顺序如何构建仍然很模糊;在我所经历的情况下,似乎较早的声明胜过后来的声明。

谁能澄清这是否是规范?

4

1 回答 1

5

关于覆盖外部存储库的文档含糊不清,但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.

于 2020-03-12T14:24:41.437 回答