如何正确使用Bazel transitions实现单命令多架构构建
Bazel 多平台单命令构建规则实现
现有代码的核心问题
- 配置键名写错:Bazel 控制目标平台的命令行参数是 --platforms(复数),你代码里写的
//command_line_option:platform(单数)不会生效。 - 缺少transition必需的白名单属性,规则会直接加载失败。
- 直接给两个属性挂同一个split transition会导致每个依赖都被同时构建两个平台版本,不符合你要binary_a对应平台A、binary_b对应平台B的需求。
- 规则实现没有声明输出、透传依赖产物,执行build时不会触发两个cc_binary的构建。
完整可运行代码
把你defs.bzl的内容替换为如下实现:
# 面向平台A的单值transition def _platform_a_transition_impl(settings, attr): return { "//command_line_option:platforms": "//path/to/your:platform_a" # 替换为你项目中平台A的实际label } platform_a_transition = transition( implementation = _platform_a_transition_impl, inputs = [], outputs = ["//command_line_option:platforms"], ) # 面向平台B的单值transition def _platform_b_transition_impl(settings, attr): return { "//command_line_option:platforms": "//path/to/your:platform_b" # 替换为你项目中平台B的实际label } platform_b_transition = transition( implementation = _platform_b_transition_impl, inputs = [], outputs = ["//command_line_option:platforms"], ) def _my_multiarch_rule_impl(ctx): # 提取两个不同平台配置下构建出的可执行文件 # 经过transition的依赖在ctx.attr中是长度为1的列表,取索引0即可拿到对应配置的提供者 bin_a = ctx.attr.binary_a[0][DefaultInfo].files_to_run.executable bin_b = ctx.attr.binary_b[0][DefaultInfo].files_to_run.executable # 声明当前规则的两个输出文件 out_a = ctx.actions.declare_file(f"{ctx.label.name}_platform_a") out_b = ctx.actions.declare_file(f"{ctx.label.name}_platform_b") # 将依赖构建出的二进制复制到当前规则的输出目录,方便查找 ctx.actions.run_shell( inputs = [bin_a, bin_b], outputs = [out_a, out_b], command = f"cp {bin_a.path} {out_a.path} && cp {bin_b.path} {out_b.path}" ) # 返回默认提供者,将两个文件纳入当前规则的构建产物 return [DefaultInfo(files = depset([out_a, out_b]))] my_custom_multi_arch_rule = rule( implementation = _my_multiarch_rule_impl, attrs = { "binary_a": attr.label( cfg = platform_a_transition, executable = True, mandatory = True, ), "binary_b": attr.label( cfg = platform_b_transition, executable = True, mandatory = True, ), # *必须*添加该隐式白名单属性,否则自定义transition无法使用 "_allowlist_function_transition": attr.label( default = "@bazel_tools//tools/allowlists/function_transition_allowlist" ) } )
使用说明
你原有的BUILD文件写法不需要调整,直接执行如下命令即可一次性构建两个平台的二进制:
bazel build //path/to/your:multiarch_build
构建完成后,两个平台的二进制会直接输出在bazel-bin/path/to/your/目录下,文件名分别为multiarch_build_platform_a和multiarch_build_platform_b。
可选优化
如果你不需要把二进制复制到规则输出目录,也可以直接合并两个依赖的文件集合返回,省去复制动作,只是产物路径会藏在对应transition的配置目录下,查找不太方便:
def _my_multiarch_rule_impl(ctx): all_files = [] all_files.append(ctx.attr.binary_a[0][DefaultInfo].files) all_files.append(ctx.attr.binary_b[0][DefaultInfo].files) return [DefaultInfo(files = depset(transitive = all_files))]
内容的提问来源于stack exchange,提问作者seth
相关产品推荐
相关产品推荐

