为何ctx.actions.run无法引用生成文件作为输入?求解决方案
解决Bazel规则中生成文件在沙盒中找不到的问题
问题概述
编写Bazel规则时,通过ctx.actions.expand_template生成脚本,再用ctx.actions.run执行该脚本。已将生成的脚本和依赖规则生成的filelist文件(含文件名称、路径的生成型文件)作为inputs传入,但执行脚本时找不到这些filelist文件。查看沙盒路径发现,filelist存在于execroot/my_rules/bazel-out/k8-fastbuild/bin/my_test子目录中,但脚本引用的沙盒根目录下无对应文件。
问题原因
- 变量名错误:代码中
ctx.actions.expand_template的output参数使用了未定义的compile_script变量,后续executable引用的路径也对应错误,导致执行的脚本并非预期生成的文件。 - 绝对路径无效:
ctx.actions.run中使用主机绝对路径compile_script.path指定可执行脚本,沙盒环境无法解析该路径。 - 依赖文件收集不完整:若
flists_list未正确收集依赖规则生成的所有filelist文件,会导致这些文件未被传入沙盒。
修复方案
1. 修正变量名错误
将ctx.actions.expand_template的output改为之前声明的my_script,确保脚本生成到正确的文件中:
my_script = ctx.actions.declare_file("my_script.sh") ctx.actions.expand_template( output = my_script, # 修正为已声明的my_script变量 template = ctx.file._my_template, substitutions = { "{TOP}": "{}".format(top_name), "{FLISTS}": " ".join(["-f {}".format(f.short_path) for f in flists_list]), ... }, )
2. 使用相对路径指定可执行脚本
在ctx.actions.run中,改用my_script.short_path作为可执行文件路径,确保沙盒环境能正确识别:
ctx.actions.run( inputs = depset(compile_srcs), outputs = [outputs], executable = my_script.short_path, # 使用沙盒内的相对路径 env = { "HOME": "/home/grrrr", }, )
3. 完整收集依赖文件
确认flists_list正确收集了所有依赖规则的输出文件,可通过遍历deps属性获取:
# 从deps中收集所有输出文件到flists_list flists_list = [] for dep in ctx.attr.deps: flists_list.extend(dep.files.to_list())
4. 验证输入文件传递
确保compile_srcs包含所有必要文件(脚本、filelist、源文件),并通过depset传递给ctx.actions.run:
compile_srcs = flists_list + srcs_list + [my_script] ctx.actions.run( inputs = depset(compile_srcs), # 使用depset确保文件完整传递 ... )
修正后的规则片段
def _my_rule_impl(ctx): ... my_script = ctx.actions.declare_file("my_script.sh") ctx.actions.expand_template( output = my_script, template = ctx.file._my_template, substitutions = { "{TOP}": "{}".format(top_name), "{FLISTS}": " ".join(["-f {}".format(f.short_path) for f in flists_list]), ... }, ) # 收集所有依赖的输出文件 flists_list = [] for dep in ctx.attr.deps: flists_list.extend(dep.files.to_list()) compile_srcs = flists_list + srcs_list + [my_script] outputs = ctx.outputs.executable ctx.actions.run( inputs = depset(compile_srcs), outputs = [outputs], executable = my_script.short_path, env = { "HOME": "/home/grrrr", }, ) allfiles = depset(compile_srcs) runfiles = ctx.runfiles(files = compile_srcs) return [DefaultInfo( files = allfiles, runfiles = runfiles, )] my_rule = rule( implementation = _my_rule_impl, attrs = { "deps": attr.label_list( mandatory = True, ), "_my_template": attr.label( allow_single_file = True, default = Label("@my_rules//my_test:my_script.sh.template"), ), ... }, executable = True, )
内容的提问来源于stack exchange,提问作者Grrrr
相关产品推荐
相关产品推荐

