2022 年 BazelCon 将于 11 月 16 日至 17 日在纽约和线上举办。
立即报名!

针对远程执行调整 Bazel 规则

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本页面适用于编写自定义构建和测试规则的 Bazel 用户,他们希望在远程执行环境中了解 Bazel 规则的要求。

远程执行允许 Bazel 在单独的平台(例如数据中心)上执行操作。Bazel 使用 gRPC 协议进行远程执行。您可以使用 Bazel-buildfarm 尝试远程执行,开源项目是一个旨在提供分布式远程执行平台的开源项目。

本页中使用以下术语指代不同的环境类型或平台:

  • 托管平台 - Bazel 在其中运行。
  • 执行平台 - 运行 Bazel 操作的位置。
  • 目标平台 - 构建输出(以及一些操作)的运行平台。

概览

在配置 Bazel build 以进行远程执行时,您必须遵循本页面中所述的指南,以确保该 build 远程执行时不会出现错误。这是由于远程执行的性质所致,即:

  • 隔离式构建操作 - 构建工具不保留状态,依赖项不会在它们之间泄露。

  • 多样化的执行环境。 本地构建配置并不总是适合远程执行环境。

本页面介绍为远程执行实现自定义 Bazel 构建和测试规则时可能出现的问题,以及如何避免这些问题。它涵盖以下主题:

通过工具链规则调用构建工具

Bazel 工具链规则是一种配置提供程序,可告知构建工具要使用哪些构建工具(如编译器和链接器),以及如何使用规则的创建者定义的参数来配置这些工具。工具链规则允许构建和测试规则以与远程执行兼容的可预测预配置方式调用构建工具。例如,使用工具链规则,而不是通过 PATHJAVA_HOME 或可能未设定为遥控器中的相同值(或根本不设置)的其他局部变量调用构建工具执行环境。

目前有适用于 Bazel 构建和测试规则的工具链规则斯卡拉ust 面以及转到,以及针对其他语言和工具(如bash 如果规则使用的工具不存在工具链规则,请考虑创建工具链规则

管理隐式依赖项

如果构建工具可以跨构建操作访问依赖项,这些操作将在远程执行时失败,因为每个远程构建操作都是与其他操作分开执行的。一些构建工具会在构建操作中保留状态,并访问尚未明确包含在工具调用中的依赖项,这将导致远程执行的构建操作失败。

例如,当 Bazel 指示有状态编译器在本地构建 foo 时,该编译器会保留对 foo 构建输出的引用。 然后,当 Bazel 指示编译器构建 bar 时,后者依赖于 foo,但不会在 BUILD 文件中明确说明该依赖项,以便收录到 {101 编译器调用,只要同一编译器实例同时执行这两项操作(通常在本地执行),操作就会成功执行。 不过,由于在远程执行场景中,每个构建操作都会执行单独的编译器实例,因此编译器状态和 barfoo 的隐式依赖项都将丢失构建将会失败。

为了帮助检测和消除这些依赖项问题,Bazel 0.14.1 提供了本地 Docker 沙盒,该沙盒对依赖项的限制与远程执行相同。使用沙盒,确定并解决与依赖项相关的构建错误,为远程执行做好准备。如需了解详情,请参阅使用 Docker 沙盒排查 Bazel 远程执行问题

管理依赖于平台的二进制文件

通常情况下,由于依赖项可能不匹配,在主机平台上构建的二进制文件无法在任意远程执行平台上安全执行。例如,随 Bazel 提供的 SingleJar 二进制文件以主机平台为目标。不过,对于远程执行,必须在构建代码的过程中编译 SingleJar,使其以远程执行平台为目标。(请参阅目标选择逻辑。)

请勿以源代码的形式提供 build 所需的 Build Tools 二进制文件,除非您确定它们将在执行平台中安全运行。而是执行以下操作之一:

  • 发布或引用该工具的源代码,以便针对远程执行平台进行构建。

  • 将该工具预安装到远程执行环境(例如,工具链容器)中(如果该工具足够稳定),并使用工具链规则在构建中运行该工具。

管理配置式 WORKSPACE 规则

Bazel 的 WORKSPACE 规则可用于探测构建平台所需的工具和库(对于本地构建,也是 Bazel 的执行平台)。如果构建明确依赖于本地构建工具和工件,并且远程执行平台与主机平台不相同,则会在远程执行期间失败。

WORKSPACE 规则执行的以下操作与远程执行不兼容:

  • 构建二进制文件。 在 WORKSPACE 规则中执行编译操作会导致二进制文件与远程执行平台不兼容(如果与主机平台不同)。

  • 安装 pip 软件包。 通过 WORKSPACE 规则安装的 pip 软件包要求在主机平台上预安装其依赖项。专门为主机平台构建的此类软件包与主机执行平台不同时,将与远程执行平台不兼容。

  • 指向本地工具或工件的符号链接。 指向通过 WORKSPACE 规则创建的主机平台上安装的工具或库的符号链接会导致构建在远程执行平台上失败,因为 Bazel 无法找到它们。请使用标准构建操作创建符号链接,以便符号链接工具和库可从 Bazel 的 runfiles 树访问。请勿使用 repository_ctx.symlink 对外部 repo 目录之外的目标文件进行符号链接。

  • 屏蔽主机平台。 避免在 Bazel runfiles 树之外创建文件、创建环境变量和执行类似操作,因为它们可能会在远程执行平台上意外运行。

为帮助发现潜在的非封闭行为,您可以使用工作区规则日志

如果外部依赖项执行依赖于主机平台的具体操作,则应在 WORKSPACE 和构建规则之间拆分这些操作,如下所示:

  • 平台检查和依赖项枚举。 这些操作通过 WORKSPACE 规则在本地执行是安全的,该规则可以检查已安装的库、下载必须构建的软件包以及准备要编译的工件。对于远程执行,这些规则还必须支持使用预检查后的工件,以提供通常在主机平台检查期间获得的信息。通过预先检查的工件,Bazel 可以描述依赖项,就像它们是本地依赖项一样。为此,请使用条件语句或 --override_repository 标志。

  • 生成或编译特定于目标的工件和平台变更。 这些操作必须通过常规构建规则执行。在构建期间,必须执行为外部依赖项生成目标专用工件的操作。

为了更轻松地生成预执行工件以进行远程执行,您可以使用 WORKSPACE 规则来发出生成的文件。您可以在每个新执行环境(例如在每个工具链容器内)中运行这些规则,并将远程执行构建的输出输出到源代码库中以供参考。

例如,对于 cudapython 的 Tensorflow 规则,WORKSPACE 规则会生成以下 BUILD files。 在本地执行时,会使用通过检查主机环境生成的文件。对于远程执行,环境变量上的条件语句允许规则使用已签入代码库的文件。

BUILD文件声明genrules既能在本地运行又能远程运行,并执行以前通过repository_ctx.symlink如下所示此处中披露政府所要求信息的数量和类型。