You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 10:42:22