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

如何在Bazel中创建带默认参数的可执行代理目标?

在Bazel中创建带默认参数的可执行代理目标

问题描述

我有一个Bazel可执行目标target,可通过以下命令运行:

bazel run //my/lib:target -- --param=pam --pam

我希望创建一个预配置的默认执行目标bazel run //my/lib:target_with_defaults,使其等效于上述命令。我预想的写法如下:

executable(
    name = "target",
    deps = [":target_lib"],
)

executable_proxy(
    name = "target_with_defaults",
    deps = [":target"],
    defaults = ["--param=pam", "--pam"]
)

请问这在Bazel中是否可以实现?如果无法实现,这违反了Bazel的哪些设计理念?

我的需求背景是:后续需要收集所有executable_proxy目标以自动运行测试。


实现方案

Bazel原生没有executable_proxy这类规则,但可以通过两种方式实现你的需求:

1. 使用sh_binary包装

编写简单的shell脚本作为包装器,调用原目标并传入默认参数:

executable(
    name = "target",
    deps = [":target_lib"],
)

sh_binary(
    name = "target_with_defaults",
    srcs = ["target_wrapper.sh"],
    data = [":target"],
)

对应的target_wrapper.sh内容:

#!/bin/bash
source "$0.runfiles/io_bazel_rules_sh/shlib/lib/rlocation.sh"
$(rlocation my/lib/target) --param=pam --pam "$@"

这里用rlocation工具可以自动获取Bazel运行时原目标的正确路径,避免硬编码路径的问题。

2. 自定义Starlark规则

如果需要批量创建这类代理目标,可以自定义规则封装逻辑:

def _executable_proxy_impl(ctx):
    script = ctx.actions.declare_file(ctx.attr.name + ".sh")
    ctx.actions.write(
        output = script,
        content = """#!/bin/bash
source "$0.runfiles/io_bazel_rules_sh/shlib/lib/rlocation.sh"
$(rlocation {target_label}) {default_args} "$@"
""".format(
            target_label = ctx.attr.target.label,
            default_args = " ".join(ctx.attr.defaults),
        ),
        is_executable = True,
    )
    return [DefaultInfo(
        executable = script,
        runfiles = ctx.runfiles(files = [ctx.attr.target]) + ctx.attr.target[DefaultInfo].default_runfiles,
    )]

executable_proxy = rule(
    implementation = _executable_proxy_impl,
    attrs = {
        "target": attr.label(executable = True, cfg = "target"),
        "defaults": attr.string_list(),
    },
    executable = True,
)

使用方式和你预想的一致:

executable(
    name = "target",
    deps = [":target_lib"],
)

executable_proxy(
    name = "target_with_defaults",
    target = ":target",
    defaults = ["--param=pam", "--pam"],
)

关于设计理念的说明

Bazel原生没有提供这类规则,主要源于以下设计理念:

  • 构建与运行分离:Bazel核心聚焦构建产物的生成,运行时参数属于执行阶段配置,原生规则不会直接封装这类运行时逻辑,避免模糊构建与执行的边界。
  • 显式可追溯性:Bazel要求依赖和构建逻辑完全显式,直接封装运行参数的规则会增加配置追溯的复杂度,不符合其"一切可追溯"的设计原则。
  • 通用性优先:Bazel只保留通用基础规则,个性化场景需求(如参数封装)由用户通过脚本或自定义规则实现,保证核心规则集的简洁性。

需求适配

对于你后续收集代理目标自动运行测试的需求:

  • 若用自定义规则,可通过bazel query 'kind("executable_proxy", //...)'批量获取目标;
  • 若用sh_binary,可给包装目标添加特定标签(如tags = ["executable_proxy"]),再通过bazel query 'attr(tags, "executable_proxy", //...)'筛选。

内容的提问来源于stack exchange,提问作者y.selivonchyk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:52:39