如何在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
相关产品推荐
相关产品推荐

