本页面适用于编写自定义构建和测试规则的 Bazel 用户 希望了解 远程执行。
远程执行允许 Bazel 在单独的平台上执行操作,例如 数据中心Bazel 使用 gRPC 协议 远程执行。您可以尝试使用以下代码远程执行 bazel-buildfarm、 旨在提供分布式远程执行功能的开源项目 平台。
本页在提及不同的技术时使用了以下术语 环境类型或平台:
- 托管平台 - 运行 Bazel 的位置。
- 执行平台 - 运行 Bazel 操作的地方。
- 目标平台 - 构建输出(和某些操作)的运行位置。
概览
在配置 Bazel 构建以进行远程执行时,必须遵循 确保构建远程执行的 不会发生错误。这取决于远程执行的性质,即:
隔离构建操作。构建工具不会保留状态和依赖项 它们之间不能泄露
丰富多样的执行环境。本地构建配置并非总是如此 适合远程执行环境。
本页面介绍实现自定义 Bazel 时可能出现的问题 构建和测试远程执行规则以及如何避免这些规则。其中介绍了 以下主题:
通过工具链规则调用构建工具
Bazel 工具链规则是一个配置提供程序,用于告知构建规则
要使用的构建工具(例如编译器和链接器)以及如何配置这些工具
使用由规则创建者定义的参数工具链规则允许构建
和测试规则,以可预测的预配置方式调用构建工具
支持远程执行例如,使用工具链规则
而不是通过 PATH
、JAVA_HOME
或其他本地变量来调用构建工具
在远程容器中可能未设置为等效值(或根本没有)的变量,
执行环境
目前存在适用于 Bazel 构建和测试规则的工具链规则 Scala、 Rust、 和 Go, 新的工具链规则正在陆续针对其他语言和工具,例如 bash。 如果您的规则所用工具不存在工具链规则,请考虑 创建工具链规则。
管理隐式依赖项
如果构建工具可以在构建操作之间访问依赖项,那么这些操作 远程执行时会失败,因为执行了每个远程构建操作 与众不同。有些构建工具会在构建操作和 访问此工具中未明确包含的依赖项 调用,这将导致远程执行的构建操作失败。
例如,当 Bazel 指示有状态编译器在本地构建 foo 时, 编译器会保留对 foo 的构建输出的引用。当运行 Bazel 时 会指示编译器构建依赖于 foo 的 bar,而不 在 BUILD 文件中明确指出要包含在 相应操作,那么只要与之前相同的 编译器实例会针对这两项操作执行(如同本地执行的典型情况)。 不过,由于在远程执行场景中,每个构建操作都会执行 单独的编译器实例、编译器状态和 Bar 的隐式依赖项 foo 将丢失,并且构建将失败。
为帮助检测并消除这些依赖关系问题,Bazel 0.14.1 提供了 本地 Docker 沙盒,其对依赖项的限制与远程容器相同 执行。使用沙盒为远程执行准备 build,方法是 识别和解决与依赖项相关的构建错误。请参阅对使用 Docker Sandbox 的 Bazel Remote Execution 进行问题排查 。
管理依赖于平台的二进制文件
通常,在托管平台上构建的二进制文件无法在 任意远程执行平台,因为依赖项可能不匹配。 例如,随 Bazel 提供的 SingleJar 二进制文件以主机平台为目标。 但是,对于远程执行,必须在进程中编译 SingleJar 构建代码,使其以远程执行平台为目标。(请参阅 目标选择逻辑。)
请勿随源代码一起交付 build 所需的构建工具的二进制文件 除非您确定它们会在您的执行平台中安全运行。相反, 以下项之一:
发布该工具的源代码,或在外部引用该工具,以便能够对其进行编译 专为远程执行平台而构建。
将该工具预安装到远程执行环境中(例如, 工具链容器),只要它足够稳定,然后使用工具链规则来运行 。
管理配置式 WORKSPACE 规则
Bazel 的 WORKSPACE
规则可用于探测主机平台中的工具
构建所需的库和库,对于本地构建而言,这也是 Bazel 的
执行平台构建是否明确依赖于本地构建工具和
工件,如果远程执行平台在远程执行期间
与托管平台不相同
WORKSPACE
规则执行的以下操作不兼容
远程执行:
构建二进制文件 -正在
WORKSPACE
规则中执行编译操作 导致二进制文件与远程执行平台不兼容 (如果与托管平台不同)。安装
pip
软件包。已通过WORKSPACE
安装了pip
个软件包 规则要求其依赖项预安装在主机平台上。 专门为托管平台构建的此类软件包将 如果与主机不同,则与远程执行平台不兼容 平台。与本地工具或工件建立符号链接。指向工具或库的符号链接 安装在通过
WORKSPACE
规则创建的主机平台上会导致 构建在远程执行平台上失败,因为 Bazel 无法 找到它们。而是应该使用标准构建操作来创建符号链接,这样, 可以从 Bazel 的runfiles
访问符号链接的工具和库 树。不使用repository_ctx.symlink
对外部代码库目录之外的目标文件进行符号链接。更改主机平台。避免在 Bazel 之外创建文件
runfiles
树、创建环境变量以及类似的操作,如下所示: 它们可能会在远程执行平台上出现意外行为。
为了帮助您发现潜在的非封闭行为,您可以使用工作区规则日志。
如果外部依赖项依赖于主机执行特定操作
您应在 WORKSPACE
和 build 之间拆分这些操作
规则如下:
平台检查和依赖项枚举。这些操作包括 可通过
WORKSPACE
规则在本地执行 以及下载必须构建的软件包, 进行编译所需的工件对于远程执行,这些规则必须 也支持使用预先检查的工件来提供 通常在主机平台检查期间获得。预先选中 软件制品使 Bazel 能够像描述本地依赖项一样描述依赖项。使用 条件语句或--override_repository
标志。生成或编译特定于目标的工件和平台变更。 这些操作必须通过常规构建规则执行。会 必须执行为外部依赖项生成特定于目标的工件 构建容器。
为了更轻松地生成预检查的工件以用于远程执行,您可以使用
使用 WORKSPACE
规则发出生成的文件。您可以在每个新订单
执行环境(例如在每个工具链容器内),然后检查
将远程执行构建的输出放入源代码库以供参考。
例如,对于 cuda
的 Tensorflow 规则,
和python
WORKSPACE
规则会生成以下 BUILD files
。
对于本地执行,将使用通过检查主机环境生成的文件。
对于远程执行,条件语句
则允许规则使用已签入到以下目录的文件:
代码库
BUILD
文件会声明 genrules
可在本地和远程运行,并执行必要的处理,
之前通过 repository_ctx.symlink
完成的调用,如此处所示。