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

