如何将bazel run第一个规则的执行结果文件传递给第二个Bazel规则?
问题本质与解决方案
Bazel的构建阶段和运行阶段是完全隔离的:你通过bazel run第一个规则时生成的myfile.txt属于运行时产物,不在Bazel的构建追踪体系内,因此第二个规则在构建阶段根本无法获取到它。
正确的做法是把生成myfile.txt的逻辑移到第一个规则的构建动作中,让这个文件成为第一个规则的输出产物,这样就能被第二个规则正常依赖。
修改后的规则代码示例
1. 第一个规则:在构建阶段生成myfile.txt
def _1st_rule_impl(ctx): # 生成可执行脚本(保留原逻辑,可选) out_script = ctx.outputs.executable template = ctx.file.my_template ctx.actions.expand_template( output = out_script, template = template, substitutions = { "{ARG1}": ctx.attr.my_file_name, "{ARG2}": ctx.attr.my_file_content, } ) # 核心修改:在构建阶段生成myfile.txt,作为规则输出 my_file = ctx.actions.declare_file(ctx.attr.my_file_name) ctx.actions.run_shell( outputs = [my_file], command = "echo '{content}' > {output}".format( content = ctx.attr.my_file_content, output = my_file.path, ), ) return [ DefaultInfo( files = depset([my_file, out_script]), runfiles = ctx.runfiles(files = [out_script, my_file]) ) ] 1st_rule = rule( implementation = _1st_rule_impl, attrs = { "my_template": attr.label( allow_single_file = True, default = Label("@my_test//my_rules:my_script.sh.template"), ), "my_file_name": attr.string( default = "myfile.txt", ), "my_file_content": attr.string( default = "hello world", ), }, executable = True, outputs = { # 声明输出文件,让Bazel追踪它 "my_file": "%{my_file_name}", }, )
2. 第二个规则:获取第一个规则的输出文件
def _2nd_rule_impl(ctx): input_files = [] # 遍历依赖,提取第一个规则生成的所有输出文件 for dep in ctx.attr.deps: input_files.extend(dep[DefaultInfo].files.to_list()) # 如果需要精准筛选myfile.txt,可添加过滤逻辑 # for f in dep[DefaultInfo].files.to_list(): # if f.basename == "myfile.txt": # input_files.append(f) # 示例:生成使用该文件的可执行脚本 out = ctx.outputs.executable ctx.actions.write( output = out, content = "#!/bin/sh\necho 读取文件内容:\ncat {}".format( input_files[0].path if input_files else "", ), is_executable = True, ) return [ DefaultInfo( files = depset([out]), runfiles = ctx.runfiles(files = input_files + [out]) ) ] 2nd_rule = rule( implementation = _2nd_rule_impl, attrs = { "deps": attr.label_list( mandatory = True, ), }, executable = True, )
3. BUILD文件(无需大幅修改)
1st_rule( name = "my_1st_rule", my_file_name = "myfile.txt", my_file_content = "hello world", ) 2nd_rule( name = "my_2nd_rule", deps = [ ":my_1st_rule", ], )
验证方式
执行bazel run :my_2nd_rule,就能看到第二个规则成功读取到第一个规则在构建阶段生成的myfile.txt内容。
内容的提问来源于stack exchange,提问作者Grrrr
相关产品推荐
相关产品推荐

