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

Bazel Genrule构建后非确定性输出留存方案咨询

解决方案

1. 利用genrule的output_to_bindir属性

在genrule中设置output_to_bindir = True,仅将确定性输出加入outs列表(供后续依赖使用),非确定性的日志、报告则让脚本直接写入$(BINDIR)目录。这类文件不会被Bazel追踪,不会触发缓存失效,构建后可在项目根目录的bazel-bin下找到。

示例:

genrule(
    name = "my_genrule",
    srcs = ["input.txt"],
    outs = ["deterministic_output.txt"],
    output_to_bindir = True,
    cmd = """
        ./my_script.sh $(SRCS) $@
        # 将非确定性文件写入BINDIR目录
        cp non_deterministic.log $(BINDIR)/my_genrule.log
        cp non_deterministic_report.html $(BINDIR)/my_genrule_report.html
    """,
)

2. 编写自定义Starlark规则封装逻辑

通过自定义规则分离确定性输出与非辅助输出:将确定性文件标记为规则正式输出(供依赖链使用),非确定性文件直接复制到ctx.bin_dir下的指定路径,不纳入Bazel的缓存追踪范围。

示例简化版:

def _my_custom_rule_impl(ctx):
    deterministic_out = ctx.outputs.deterministic_out
    # 生成确定性输出
    ctx.actions.run(
        inputs = ctx.files.srcs,
        outputs = [deterministic_out],
        executable = ctx.executable.script,
        arguments = [
            deterministic_out.path,
            # 指定非确定性文件的输出路径
            ctx.bin_dir.path + "/my_rule_logs/" + ctx.label.name + ".log",
        ],
    )
    return [DefaultInfo(files = depset([deterministic_out]))]

my_custom_rule = rule(
    implementation = _my_custom_rule_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = True),
        "script": attr.label(executable = True, cfg = "exec"),
        "deterministic_out": attr.output(),
    },
)

3. 用bazel run分离报告生成逻辑

如果非确定性报告不需要在构建阶段生成,可将报告生成逻辑拆分为单独的可执行目标,通过bazel run触发执行。这种方式不会影响构建依赖链的缓存,仅在需要查看报告时运行。

示例:

# 生成确定性输出的genrule,供后续依赖使用
genrule(
    name = "generate_core_output",
    srcs = ["input.txt"],
    outs = ["core_output.txt"],
    cmd = "./core_script.sh $(SRCS) $@",
)

# 单独的报告生成可执行目标
sh_binary(
    name = "generate_report",
    srcs = ["report_script.sh"],
    data = [":core_output.txt"],
)

使用流程:先执行bazel build :generate_core_output构建核心输出,再运行bazel run :generate_report生成报告,报告可直接输出到当前工作目录。

4. 结合--output_groups过滤输出

将非确定性文件标记为独立输出组,默认构建仅生成核心输出,需要查看时通过--output_groups参数触发生成,避免干扰核心输出的缓存。

示例:

genrule(
    name = "my_genrule",
    srcs = ["input.txt"],
    outs = {
        "core": "deterministic_output.txt",
        "logs": "non_deterministic.log",
        "reports": "non_deterministic_report.html",
    },
    cmd = """
        ./my_script.sh $(SRCS) $(outs.core) $(outs.logs) $(outs.reports)
    """,
)

默认构建:bazel build :my_genrule(仅生成核心输出,缓存正常)
查看报告时:bazel build :my_genrule --output_groups=logs,reports(生成非确定性文件,不影响核心输出缓存)


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:08:12