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
Apple 规则不支持平台,并且尚未安排支持。
您仍然可以使用 平台映射,在 Apple build 中使用平台 API(例如,在混合使用 Apple 规则和纯 C++ 进行 build 时)。
其他语言
如果您拥有语言规则集,请参阅迁移规则集以添加支持。
背景
引入了平台和工具链,以标准化软件项目针对不同架构和交叉编译的方式。
这一功能灵感源于我们观察到语言维护人员已经以临时、不兼容的方式在执行此操作。例如,C++ 规则使用 --cpu 和 --crosstool_top 来声明目标 CPU 和工具链。这两种方式都无法正确模拟“平台”。这导致了不自然且不正确的构建。
Java、Android 和其他语言都开发了自己的标志,用于实现类似目的,但这些标志彼此之间并不兼容。这使得跨语言构建变得令人困惑且复杂。
Bazel 适用于大型多语言多平台项目。这就要求我们以更规范的方式支持这些概念,包括提供清晰的标准 API。
迁移需求
升级到新 API 需要完成两项工作:发布 API 和升级规则逻辑以使用该 API。
第一个已完成,但第二个正在进行中。这包括确保定义特定于语言的平台和工具链,语言逻辑通过新 API(而非 --crosstool_top 等旧标志)读取工具链,以及 config_setting 通过新 API(而非旧标志)进行选择。
这项工作简单明了,但需要针对每种语言分别进行,并且需要提前充分告知项目所有者,以便他们针对即将发生的变化进行测试。
因此,这是一项持续进行的迁移。
目标
当所有项目都以以下形式构建时,此迁移即完成:
bazel build //:myproject --platforms=//:myplatform这意味着:
- 项目的规则会为
//:myplatform选择合适的工具链。 - 项目的依赖项会为
//:myplatform选择合适的工具链。 //:myplatform引用了CPU、OS和其他通用、与语言无关的属性的常见声明- 所有相关
select()都与//:myplatform正确匹配。 //:myplatform定义在一个清晰易懂的位置:如果平台是项目独有的,则在项目的代码库中;如果平台是所有使用项目都可以找到的通用位置,则在其中
旧标志(例如 --cpu、--crosstool_top 和 --fat_apk_cpu)将在确保安全的前提下尽快被弃用和移除。
最终,这将成为配置架构的唯一方式。
迁移项目
如果您使用支持平台的语言进行构建,则构建应已可通过以下调用正常运行:
bazel build //:myproject --platforms=//:myplatform如需了解确切的详细信息,请参阅状态和您所用语言的文档。
如果某种语言需要使用标志来启用平台支持,您还需要设置该标志。如需了解详情,请参阅状态。
为了让项目能够构建,您需要检查以下内容:
//:myplatform必须存在。通常,项目所有者负责定义平台,因为不同的项目面向不同的机器。 请参阅默认平台。您要使用的工具链必须存在。如果使用标准工具链,语言所有者应提供有关如何注册它们的说明。如果您要编写自己的自定义工具链,需要在
MODULE.bazel文件中或使用--extra_toolchains注册它们。如果您的 build 混合使用了支持平台和不支持平台的语言,您可能需要平台映射来帮助旧版语言与新 API 搭配使用。如需了解详情,请参阅平台映射。
如果您仍有问题,请联系支持团队。
默认平台
项目所有者应定义明确的平台来描述他们要构建的目标架构。然后,使用 --platforms 触发这些事件。
如果未设置 --platforms,Bazel 会默认使用表示本地 build 机器的 platform。此属性在 @platforms//host(别名为 @bazel_tools//tools:host_platform)处自动生成,因此无需明确定义。它将本地机器的 OS 和 CPU 与 @platforms 中声明的 constraint_value 相关联。
select()
项目可以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" },或者使用平台映射在迁移期间同时支持这两种样式。
window.
迁移规则集
如果您拥有规则集并希望支持平台,则需要执行以下操作:
让规则逻辑通过 toolchain API 解析工具链。请参阅工具链 API (
ctx.toolchains)。可选:定义
--incompatible_enable_platforms_for_my_language标志,以便规则逻辑在迁移测试期间通过新 API 或旧标志(如--crosstool_top)交替解析工具链。定义构成平台组件的相关属性。请参阅通用平台属性
定义标准工具链,并通过规则的注册说明(详情)让用户可以访问这些工具链
确保
select()和配置转换支持平台。这是最大的挑战。对于多语言项目,这尤其具有挑战性(如果所有语言都无法读取--platforms,项目可能会失败)。
如果您需要与不支持平台的规则混用,可能需要使用平台映射来弥合差距。
通用平台属性
OS 和 CPU 等常见的跨语言平台属性应在 @platforms 中声明。这有助于鼓励分享、标准化和跨语言兼容性。
规则特有的属性应在规则的代码库中声明。这样一来,您就可以清楚地了解规则负责的具体概念。
如果您的规则使用自定义用途的操作系统或 CPU,则应在规则的代码库中声明这些操作系统或 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 使用此功能来保证所有设置(包括基于平台的设置和旧版设置)在整个 build 过程中(包括通过转换)始终保持一致。
默认情况下,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",
)
toolchain 是 Starlark 规则。其属性声明了语言的工具(例如 compiler =
"//mytoolchain:custom_gcc")。其提供程序会将此信息传递给需要使用这些工具进行构建的规则。
工具链会声明其可以定位的机器的 constraint_value (target_compatible_with = ["@platforms//os:linux"]) 以及其工具可以运行的机器 (exec_compatible_with = ["@platforms//os:mac"])。
构建 $ bazel build //:myproject --platforms=//:myplatform 时,Bazel 会自动选择可在构建机器上运行并为 //:myplatform 构建二进制文件的工具链。这称为“工具链解析”。
可以在 MODULE.bazel 文件中使用 register_toolchains 注册可用的工具链集,也可以在命令行中使用 --extra_toolchains 注册。
如需了解详情,请参阅此处。
问题
如需一般性支持以及有关迁移时间表的疑问,请与 bazel-discuss 或相应规则的所有者联系。
如需讨论平台/工具链 API 的设计和发展,请与 bazel-dev 联系。