迁移到平台

报告问题 查看源代码

Bazel 为多架构和交叉编译 build 的建模平台工具链提供了复杂的支持

本页面总结了这项支持服务的状态。

另请参阅:

状态

C++

设置 --incompatible_enable_cc_toolchain_resolution 后,C++ 规则使用平台选择工具链。

这意味着,您可以使用以下命令配置 C++ 项目:

bazel build //:my_cpp_project --platforms=//:myplatform

而不使用旧版:

bazel build //:my_cpp_project` --cpu=... --crosstool_top=...  --compiler=...

在 Bazel 7.0 中,此功能默认处于启用状态 (#7260)。

如需使用平台测试 C++ 项目,请参阅迁移项目配置 C++ 工具链

Java

Java 规则使用平台来选择工具链。

这取代了旧版标志 --java_toolchain--host_java_toolchain--javabase--host_javabase

如需了解详情,请参阅 Java 和 Bazel

Android

设置 --incompatible_enable_android_toolchain_resolution 后,Android 规则会使用平台来选择工具链。

这意味着,您可以通过以下方式配置 Android 项目:

bazel build //:my_android_project --android_platforms=//:my_android_platform

而不是使用 --android_crosstool_top--android_cpu--fat_apk_cpu 等旧版标志。

在 Bazel 7.0 中,此功能默认处于启用状态 (#16285)。

如需使用平台测试 Android 项目,请参阅迁移项目

苹果

Apple 规则不支持平台,尚未安排提供支持。

您仍然可以将平台 API 用于 Apple build(例如,混合使用 Apple 规则和纯 C++ 进行构建时)和平台映射

其他语言

如果您拥有语言规则集,请参阅迁移规则集以添加支持。

背景

引入了平台和工具链,以对软件项目如何针对不同架构进行开发并实现交叉编译实现标准化。

这一发现启发了语言维护人员已经在临时、不兼容的方式这样做。例如,C++ 规则使用 --cpu--crosstool_top 来声明目标 CPU 和工具链。这两者都无法正确地为“平台”建模。这会产生尴尬且错误的 build。

为了实现类似目的,Java、Android 和其他语言发展出了自己的标志,这些标志之间没有互操作性。这让跨语言构建变得困惑和复杂。

Bazel 适用于大型、多语言和多平台项目。这就需要对这些概念提供更有针对性的支持,包括明确的标准 API。

需要迁移

升级到新 API 需要完成两项工作:发布 API 和升级规则逻辑以使用它。

第一个任务已完成,但第二个任务正在进行。这包括确保已定义特定于语言的平台和工具链,语言逻辑通过新 API 而不是 --crosstool_top 等旧标志读取工具链,以及 config_setting 选择新 API 而不是旧标志。

这项工作很简单,但需要针对每种语言分别付出努力,并且会向项目所有者发出合理警告,提醒他们测试即将发生的更改。

因此,这是一项持续迁移的原因。

目标

当所有项目都使用以下表单构建时,此迁移完成:

bazel build //:myproject --platforms=//:myplatform

这意味着:

  1. 您的项目规则会为 //:myplatform 选择正确的工具链。
  2. 项目的依赖项会为 //:myplatform 选择正确的工具链。
  3. //:myplatform 引用 CPUOS 和其他与语言无关的通用属性的通用声明
  4. 所有相关 select() 都与 //:myplatform 正确匹配。
  5. //:myplatform 在一个清晰且可访问的位置进行定义:如果平台是您的项目所独有的,或者在所有使用方项目的通用位置都可以在项目的代码库中定义

在安全的情况下,我们会立即废弃并移除 --cpu--crosstool_top--fat_apk_cpu 等旧标志。

最终,这将是配置架构的唯一方式。

迁移项目

如果您使用支持平台的语言构建应用,您的 build 应该已经可以使用如下调用:

bazel build //:myproject --platforms=//:myplatform

如需了解确切详情,请参阅状态和您所用语言的文档。

如果某个语言需要某个标志以启用平台支持,您还需要设置该标志。如需了解详情,请参阅状态

为了能够构建项目,您需要检查以下内容:

  1. //:myplatform 必须存在。通常,项目所有者需负责定义平台,因为不同的项目以不同的机器为目标。请参阅默认平台

  2. 您要使用的工具链必须存在。如果使用库存工具链,则语言所有者应添加有关如何注册它们的说明。如果要编写自己的自定义工具链,您需要在 MODULE.bazel 文件或 --extra_toolchainsregister它们。

  3. select()配置转换必须正确解析。请参阅 select()转换

  4. 如果您的 build 混用了支持和不支持平台的语言,您可能需要平台映射,以帮助旧版语言与新 API 兼容。如需了解详情,请参阅平台映射

如果仍有问题,请与我们联系寻求支持。

默认平台

项目所有者应定义明确的平台,以描述要针对哪些架构构建应用。然后,这些操作会通过 --platforms 触发。

如果未设置 --platforms,Bazel 会默认使用表示本地构建机器的 platform。它是在 @platforms//host 自动生成的(别名为 @bazel_tools//tools:host_platform),因此无需明确定义。它会将本地机器的 OSCPU@platforms 中声明的 constraint_value 进行映射。

select()

项目可以在 constraint_value 目标上执行 select() 操作,但无法在平台上完成操作。这是有意为之,以便 select() 尽可能支持各种机器。除非有更具体的原因,否则包含特定于 ARM 的源代码的库应支持所有采用 ARM所有机器。

如需选择一个或多个 constraint_value,请使用:

config_setting(
    name = "is_arm",
    constraint_values = [
        "@platforms//cpu:arm",
    ],
)

这相当于传统上在 --cpu 上选择:

config_setting(
    name = "is_arm",
    values = {
        "cpu": "arm",
    },
)

如需了解更多详情,请参阅此处

--cpu--crosstool_top 等上的 select 无法理解 --platforms。将项目迁移到平台时,您必须将其转换为 constraint_values 或使用平台映射,以便在迁移过程中支持这两种样式。

转场效果

Starlark 过渡会更改 build 图的下部分标志。如果您的项目使用的转换设置了 --cpu--crossstool_top 或其他旧版标志,则读取 --platforms 的规则不会看到这些更改。

将项目迁移到平台时,您必须将 return { "//command_line_option:cpu": "arm" } 等更改转换为 return { "//command_line_option:platforms": "//:my_arm_platform" },或使用平台映射在迁移期间支持这两种样式。

迁移规则集

如果您有规则集并且希望支持平台,则需要:

  1. 使用工具链 API 让规则逻辑解析工具链。请参阅工具链 API (ctx.toolchains)。

  2. 可选:定义一个 --incompatible_enable_platforms_for_my_language 标志,以便规则逻辑在迁移测试期间通过新 API 或旧标志(如 --crosstool_top)交替解析工具链。

  3. 定义构成平台组件的相关属性。请参阅通用平台属性

  4. 定义标准工具链,并通过规则的注册说明使用户能够访问这些工具链(详细信息

  5. 确保 select()配置转换支持平台。这是最大的挑战。这对于多语言项目来说尤其具有挑战性(如果所有语言都无法读取 --platforms,则可能会失败)。

如果您需要混用不支持平台的规则,则可能需要使用平台映射来弥补差异。

通用平台属性

OSCPU 等常用的跨语言平台属性应在 @platforms 中声明。这有助于促进共享、标准化和跨语言兼容性。

您的规则独有的属性应在规则的代码库中声明。这样,您就可以保持对规则负责的特定概念的明确所有权。

如果您的规则使用自定义用途的操作系统或 CPU,应在规则的代码库中(而不是 @platforms)进行声明。

平台映射

平台映射是一种临时 API,可让平台感知型逻辑与旧版逻辑在同一 build 中混搭。这是一个钝工具,仅用于消除不同迁移时间范围之间的不兼容性。

平台映射是 platform() 到一组相应的旧版标志或反向的映射。例如:

platforms:
  # Maps "--platforms=//platforms:ios" to "--ios_multi_cpus=x86_64 --apple_platform_type=ios".
  //platforms:ios
    --ios_multi_cpus=x86_64
    --apple_platform_type=ios

flags:
  # Maps "--ios_multi_cpus=x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
  --ios_multi_cpus=x86_64
  --apple_platform_type=ios
    //platforms:ios

  # Maps "--cpu=darwin_x86_64 --apple_platform_type=macos" to "//platform:macos".
  --cpu=darwin_x86_64
  --apple_platform_type=macos
    //platforms:macos

Bazel 使用此机制来确保在整个构建过程中(包括通过过渡)始终应用所有设置(包括基于平台的设置和旧版设置)。

默认情况下,Bazel 会从工作区根目录中的 platform_mappings 文件读取映射。您还可以设置 --platform_mappings=//:my_custom_mapping

如需了解详情,请参阅平台映射设计

API 审核

platform 是一组 constraint_value 目标

platform(
    name = "myplatform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

constraint_value 是机器属性。同一“种类”的值会分组到一个通用的 constraint_setting 下:

constraint_setting(name = "os")
constraint_value(
    name = "linux",
    constraint_setting = ":os",
)
constraint_value(
    name = "mac",
    constraint_setting = ":os",
)

toolchainStarlark 规则。它的属性声明了语言的工具(如 compiler = "//mytoolchain:custom_gcc")。其提供程序会将此信息传递给需要使用这些工具进行构建的规则。

工具链会声明可对其定位的机器的 constraint_value (target_compatible_with = ["@platforms//os:linux"]) 以及可运行其工具的机器的 constraint_value (exec_compatible_with = ["@platforms//os:mac"])。

构建 $ bazel build //:myproject --platforms=//:myplatform 时,Bazel 会自动选择可以在构建机器上运行的工具链,并为 //:myplatform 构建二进制文件。这称为“工具链解析”。

您可以使用 register_toolchainsMODULE.bazel 文件中注册,也可以使用 --extra_toolchains 在命令行中注册这组可用工具链。

如需了解详情,请点击此处

问题

如需获得常规支持或有关迁移时间表的问题,请与 bazel-think 或相应规则的所有者联系。

如需有关平台/工具链 API 的设计和演变的讨论,请与 bazel-dev 联系。

另请参阅