Remote execution 规则
https://docs.bazel.build/versions/3.7.0/remote-execution-rules.html
Remote execution 允许 Bazel 在分离的平台上(例如数据中心)执行动作。你可以用 bazel-buildfarm 来尝试 Remote execution,这个开源项目旨在提供一个分布式的 Remote execution 平台。这个页面适用于那些编写自定义构建和测试 Bazel rules 的 Bazel 用户,他们想了解 Remote execution 的上下文对 Bazel rules 有什么要求。
当引用不同的环 境或者平台时,本文件使用以下术语。
- Host plaform - Bazel 运行的地方
- Execution platform - Bazel actions 运行的地方
- Target platform - Bazel build 的输出文件(和一些 Bazel actions ???) 运行的地方
总览
当你配置 Remote execution 时,你必须遵守本文档描述的以下规则以确保 Remote execution 可以正常执行而不会出现错误,这是由于 Remote execution 的特性,即:
- 独立的构建动作(Isolated build actions)
构建工具不会保留状态并且依赖关系不会泄漏 - 多样的执行环境(Diverse execution environments)
本地构建的配置不总是适用于远程环境
本文档描述了为了 remote excution 实现自定义 Bazel build rules 和 Bazel test rules 过程中可能遇到的问题及如何避免,这包含以下几个主题:
- 通过 Toolchain rules 调用构建工具
- 管理依赖
- 管理平台相关的二进制
- Managing configure-style WORKSPACE rules ???
通过 Toolchain rules 调用构建工具
Bazel 的 Toolchain rules 是配置提供者,它告诉 Build rules 要使用的构建工具(例如编译器和链接器)如何使用并且如何根据规则创建者定义的参数来配置它们。一个 Toolchain rule 允许 Build rule 和 Test rule 以可预计的,预配置的方式调用构建工具,从而与 Remote execution 兼容。例如,使用一个 Toolchain rule 代替 PATH,JAVA_HOME 或者其他的本地变量调用构建工具,这些变量可能并没有在远程环境中设置或者本机环境和远程环境不一致。
Toolchain rules 当前已经有了 Scala,Rust 和 Go 的 Build rules 和 Test rules。新的 Toolchain rules 例如 bash 也正在开发中。如果你要使用的 Toolchain rule 不存在,考虑创建一个新的 Toolchain rule。
管理隐式依赖
如果一个构建工具能够访问各个构建操作的依赖,这些动作在远程执行时将会失败,因为每个构建动作之间都是分离的。一些构建工具会在构建操作和依赖关系间保留状态,这些依赖关系尚未明确包含在工具调用中,浙江导致远程执行的构建操作失败。
例如,当 Bazel 只是一有状态编译器在本地生成 foo 时,编译器会保留 foo 的构建输出。当 Baze 指示编译器 构建 bar 时(依赖于 foo),在没有明确说明 BUILD 文件中包含的编译调用关系时,只要在同一个编译器下执行两个动作,改动作将会成功执行,这对于本地执行而言是典型的。然而,在 Remote execution 情景下,每个构建动作是在不同的编译器实例中执行的,编译状态和 bar 的 隐式依赖 foo 将会丢失然后构建将会失败。
为了帮助检测和消除这种依赖问题,Bazel 0.14.1 提供了本地 Docker sandbox,Docker sandbox 有着和 Remote execution 相同的依赖限制。 使用 sandbox,通过识别和解决依赖相关的构建错误来为 Remote execution 做准备。
管理平台相关的二进制
通常来说,在 Host platform 上构建的二进制由于潜在的依赖不匹配问题无法安全的在任意 Remote execution 平台上运行。例如,Bazel 随附的 SingleJar 二进制以 Host platform 为目标。然而,对 Remote exection,必须在构建代码的过程中将 SingleJar 编译为适合 Remote execution 平台的目标。参见 target selection logic
不要将构建所需的构建工具的二进制文件???和需要构建的源代码一起提供,除非您确定它们它们会在您的执行环境中安全运行。否则,请采用以下任意一种操作:
- 传输或从外部引入该工具的源码,一笔那可以为 Remote execution 平台构建该工具
- 如果工具足够稳定,预先安装这些工具到远程执行环境中(例如 toolchain container),并使用 Toolchain rules 去运行
管理 configure-style WORKSPACE rules
Bazel 的 WORKSPACE ruels 能够为构建所需的工具和库用于探测 Host platform,对于本地构建,该平台也是 Bazel 的 Execution platform。如果构建明确依赖本地工具和工件,当 Host platform 和 Remote execution 的 Execution platform 不一致时 Remote execution 将会失败。
WORKSPACE rules 执行的以下操作与 Remote execution 不兼容:
- Building binary
如果 Execution platform 和 Host pkatform 不同,则在 WORKSOACE rules 中执行的编译操作会导致二进制文件与远程执行平台不兼容 - Installing pip packages
通过 WORKSPACE rules 安装的 pip 软件包要求将其依赖预先安装在 Host platform 上。如果 Remote execution platform 与 Host platform 不同,则这些软件不兼容 Remote execution platform - 符号链接到本地工具和工件
通过 WORKSPACE rules 创建的安装在 Host platform 上的通过符号链接的库和工具将导致 Remote execution 失败,因为 Bazel 不能在 Remote execution platform 上找到它们。相反,请使用标准的构建操作创建符号链接,以便可以从 Bazel 的 runfiles 树中访问符号链接的工具和库。不要使用 repositor_ctx.symlink 去链接导入仓库目录以外的文件 - Mutating he host platform
避免创建 bazel runfiles 树以外的文件,避免创建环境变量和类似操作,因为它们可能在 Remote execution platform 上行为异常
为了帮助发现潜在的非密封行为,您可以使用 Workspace rules log
如果外部依赖的执行依赖与 Host platform,我们建议按以下方式在 WORKSPACE 和 build rules 之间拆分这些操作:
- 平台检查和依赖枚举
这些操作在本地 WORKSOPACE rules 是安全的,这些规则能够检查那些库已经安装,下载必须构建的软件包以及准备编译所需的工件。对与 Remote execution,这些 rules 必须支持使用预检查工件来提供通常在主机平台检查期间获得的信息。预检查工件允许 Bazel 描述这些依赖为它们本地的依赖。为此请使用 --overide_repository 标志 - 生成或编译特定平台的工件和平台改变
这些操作必须在常规的 build rules 中执行。为外部以来向生成特定的目标的工件必须在构建期间执行。
为了更简单的生成用于 Remote execution 的预检查工件,你能使用 WORKSPACE rules 来导出生成的文件。你可以在每个新的执行环境中运行这些规则,例如在每个 toolchain container,并检查 Remote execution 构建的结果到你的源仓库的引用。
例如,对于 Tensorflow rules 的 cuda 和 python,WORKSPACE rules 提供了 BUILD files。对 Local execution 来说,使用通过检查 Host platform 提供的文件。对 Remote execution 来说,环境变量上的conditional statement允许规则使用 repo 中提供的文件。BUILD files 描述的 gnerules 在本地和远程都可以执行,然后执行以前通过 repository_ctx.symlink 导入的的必要处理,如下所示here。