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

如何用Bazel genrule为每个include文件添加对应命令行选项

为Bazel Genrule中的每个Include文件自动添加--include选项

我有一款命令行工具,支持通过重复的--include选项传入多个文件,使用示例如下:

mytool --include=some_include1 --include=some_include2 --include=... source1 source2 ...

我编写了如下Bazel规则:

filegroup(
  name = "include_group",
  srcs = ["some_include1", "some_include2"],
)

filegroup(
  name = "source_group",
  srcs = ["source1", "source2"],
)

genrule(
  name = "myrule",
  srcs = [":include_group"] + [":source_group"],
  outs = ["out.cpp"],
  tools = ["mytool"],
  cmd = "$(location :mytool) --include=$(locations :include_group) $(locations :source_group)"
)

但生成的实际命令行结果不符合预期:

mytool --include=some_include1 some_include2 source1 source2 

可以看到第二个include文件some_include2缺失了--include前缀,需要为include_group中的每个文件都自动添加对应的--include选项。


解决方法

方法1:使用Bazel内置的$(foreach)函数

直接修改genrule的cmd字段,利用foreach遍历每个include文件并拼接前缀:

genrule(
  name = "myrule",
  srcs = [":include_group", ":source_group"],
  outs = ["out.cpp"],
  tools = ["mytool"],
  cmd = "$(location :mytool) $(foreach include,$(locations :include_group),--include=$(include)) $(locations :source_group)"
)

$(foreach var, list, expr)会遍历list中的每个元素,将var替换为当前元素后展开expr。这里会为每个include文件生成--include=文件路径的字符串,最终所有字符串以空格分隔,完全符合工具的参数要求。

方法2:自定义Starlark规则(适用于复杂场景)

如果需要更灵活的参数处理或复用逻辑,可以编写自定义Starlark规则。创建mytool_rule.bzl文件:

def _mytool_rule_impl(ctx):
    tool = ctx.executable.tool
    includes = ctx.files.includes
    sources = ctx.files.sources
    output = ctx.outputs.out

    args = ctx.actions.args()
    # 为每个include添加--include前缀
    for include in includes:
        args.add("--include", include.path)
    # 添加所有源文件
    args.add_all(sources)

    ctx.actions.run(
        inputs = includes + sources,
        outputs = [output],
        executable = tool,
        arguments = [args],
    )

mytool_rule = rule(
    implementation = _mytool_rule_impl,
    attrs = {
        "tool": attr.label(executable = True, cfg = "exec", mandatory = True),
        "includes": attr.label_list(allow_files = True, mandatory = True),
        "sources": attr.label_list(allow_files = True, mandatory = True),
        "out": attr.output(mandatory = True),
    },
)

在BUILD文件中加载并使用该规则:

load("//path/to:mytool_rule.bzl", "mytool_rule")

mytool_rule(
    name = "myrule",
    tool = ":mytool",
    includes = [":include_group"],
    sources = [":source_group"],
    out = "out.cpp",
)

这种方式可读性和可维护性更强,适合后续扩展复杂的参数逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:55:42