【问题标题】:Is the order of `load` in Bazel's specification or just because of the implementation?Bazel规范中的“加载”顺序还是仅仅因为实现?
【发布时间】:2020-06-22 23:07:54
【问题描述】:

我在使用 Bazel 构建 Go 项目时遇到 a problem,发现它的根本原因是 load 导入 @io_bazel_rules_go 的顺序。

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

谁能澄清这是否是规范?

【问题讨论】:

    标签: bazel bazel-rules


    【解决方案1】:

    关于覆盖外部存储库的文档含糊不清,但https://docs.bazel.build/versions/2.2.0/external.html 可能是最好的参考。

    我的理解是:

    • WORKSPACE 或在WORKSPACE 调用的函数中声明的存储库被延迟评估。这一点很重要,因为评估存储库规则可能非常昂贵(它们往往会下载大文件),并且对于很多构建来说可能不是必需的。
    • 使用相同名称多次声明存储库不是错误。如果尚未评估存储库规则,则将使用最后的声明。
    • 在解决存储库中的任何标签时评估存储库规则。这包括:
      • 使用load 语句加载.bzl 文件。
      • 将属性中的标签传递给另一个被评估的存储库规则。
      • 在另一个被评估的存储库规则中的标签上使用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_archivegit_repository 存储库,用于规则集和直接依赖项。
      • load 用于存储库规则和依赖函数的语句。
      • 其他直接依赖项(例如,go_repository)。
      • 调用传递依赖的依赖函数。
      • 工具链注册。

    对于调试,native.existing_rules 函数非常方便。它返回到目前为止声明的所有存储库的列表,以及它们被声明的属性。定义一个调用它并打印结果的函数,然后从WORKSPACE 中的任何位置调用该函数。

    【讨论】:

    • 感谢您如此详细而简洁的回答!您的回答极大地帮助我理解了这种行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 2013-05-11
    相关资源
    最近更新 更多