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

如何在sh_binary目标中正确处理参数并封装供自定义规则调用

实现工具封装的方案

1. 用自定义规则把所有细节藏起来

可以写一个自定义规则,把tool_wrapper的依赖、路径传递这些内部逻辑全封装在规则实现里,让用这个规则的目标只需要简单调用,根本不用关心背后的工具路径或参数。

具体代码示例:

先在my_rules.bzl(或者直接在BUILD文件里)定义规则:

def _my_source_generator_impl(ctx):
    # 拿到封装好的tool_wrapper可执行文件
    tool = ctx.executable.tool_wrapper
    # 声明要生成的输出文件
    output = ctx.actions.declare_file(f"{ctx.attr.name}_generated_src.txt")
    
    # 调用工具生成文件,这里不用管内部的$(locations)替换,sh_binary已经处理完了
    ctx.actions.run(
        executable = tool,
        outputs = [output],
        arguments = [output.path],  # 如果脚本需要输出路径就传这个
    )
    
    return DefaultInfo(files = depset([output]))

my_source_generator = rule(
    implementation = _my_source_generator_impl,
    attrs = {
        "tool_wrapper": attr.label(
            executable = True,
            cfg = "exec",
            default = Label("//你的tool_wrapper所在路径:tool_wrapper"),  # 内部固定这个标签,外部不用管
        ),
    },
)

其他目标用的时候就很简单,完全不用碰外部工具的信息:

my_source_generator(
    name = "generated_my_src",
    # 这里啥额外参数都不用加
)

2. 利用sh_binary已有的参数处理逻辑

你已经在sh_binary的args里用$(locations @external//tools:binaries)自动处理路径了,所以自定义规则调用这个sh_binary时,Bazel会自动完成占位符替换,你完全不用在规则里再处理外部工具的路径,相当于把这层细节彻底封装了。

3. 应对工具标签变化的小技巧

如果@external//tools:binaries这个标签以后可能改,可以把它定义成一个常量放在.bzl文件里:

# my_rules.bzl里
EXTERNAL_TOOLS = "@external//tools:binaries"

然后修改sh_binary引用这个常量(要是在.bzl里定义sh_binary的话),或者在BUILD文件里load这个常量来用。以后标签变了只改这一处就行,进一步降低维护成本。

核心注意点

  • 自定义规则里的cfg = "exec"是确保工具在执行配置下构建,适合用来做构建工具。
  • executable = True告诉Bazel这个标签指向的是可执行文件。
  • 依赖这个规则的目标完全感知不到tool_wrapper或者外部二进制文件的存在。

内容的提问来源于stack exchange,提问作者rumbleD5

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:43:16