如何从Bazel Actions运行py_binary?执行无反应问题排查
Bazel自定义规则
ctx.actions.run未执行脚本问题排查 问题描述
参考Bazel官方示例编写matchcompiler自定义规则,计划通过ctx.actions.run调用py_binary工具(matchcompiler.py)处理cppcheck库源码文件。执行bazel build //:optimize_lib时,规则能执行到打印“Made it here.”,参数输出正确,但ctx.actions.run对应的Python脚本未执行且无报错。
规则实现代码
def _matchcompiler_impl(ctx): deps = _get_transitive_deps(ctx.attr.srcs, ctx.attr.deps) write_dir = ctx.attr.write_dir prefix = ctx.attr.prefix args = ctx.actions.args() outputs = [] raw_files = [] for dep in deps.to_list(): outputs.append(ctx.actions.declare_file("{}/{}{}".format(write_dir, prefix, dep.basename))) args.add("--read-dir=lib") args.add("--write-dir={}".format(write_dir)) args.add_all(raw_files) ctx.actions.run( inputs = deps, outputs = outputs, arguments = [args], executable = ctx.executable.tool, progress_message = "Doing Something" ) print("Made it here.") matchcompiler = rule( implementation = _matchcompiler_impl, attrs = { "srcs":attr.label_list(allow_files = [".cpp"]), "deps":attr.label_list( aspects=[cc_srcs_aspect], providers=[CcInfo] ), "tool":attr.label( default = Label(":matchcompiler"), # default pybinary executable executable = True, # must be an executable allow_files = True, cfg = "exec" # for the execution platform ), "verify":attr.bool( doc = "Verify compiled matches against on the fly parser, slow" ), "show_skipped":attr.bool( doc = "show skipped (non-static) patterns" ), "read_dir":attr.string( default="lib" ), "write_dir":attr.string( default="build" ), "prefix":attr.string(), "line":attr.bool( default=False ) }, )
BUILD文件代码
py_binary( name = "matchcompiler", srcs = [ "tools/matchcompiler.py" ], main = "tools/matchcompiler.py" ) cc_library( name = "cppcheck", hdrs = glob(["lib/*.h"], allow_empty = False), srcs = glob(["lib/*.cpp"], allow_empty = False), ) matchcompiler( name = "optimize_lib", tool = ":matchcompiler", deps = [":cppcheck"] )
排查及修复方案
1. arguments参数格式错误
ctx.actions.run的arguments字段无需将Args对象包裹在列表中,直接传入args即可。当前写法arguments = [args]会把整个Args对象作为单个参数传递给脚本,导致脚本无法解析参数,甚至静默退出。
修改后代码:
ctx.actions.run( inputs = deps, outputs = outputs, arguments = args, # 去掉外层列表 executable = ctx.executable.tool, progress_message = "Doing Something" )
2. raw_files为空列表
代码中args.add_all(raw_files)传入了空列表,脚本可能因无输入文件直接跳过核心逻辑。需确认_get_transitive_deps是否正确收集到文件,或在循环中将依赖文件加入raw_files:
修改示例:
for dep in deps.to_list(): outputs.append(ctx.actions.declare_file("{}/{}{}".format(write_dir, prefix, dep.basename))) raw_files.append(dep) # 添加此行,将依赖文件加入输入参数
3. 未返回输出文件提供者
matchcompiler规则未返回输出文件的DefaultInfo,Bazel会认为该规则无有效输出,从而跳过动作执行。需在规则实现末尾添加返回语句:
修改后代码:
print("Made it here.") # 添加返回输出文件的提供者 return DefaultInfo(files = depset(outputs))
4. prefix参数未设置
optimize_lib目标未指定prefix属性,生成输出文件路径时会出现build/.cpp这类无效路径,Bazel可能因无法创建无效路径文件而跳过动作。需在BUILD文件中补充prefix字段:
修改后BUILD代码:
matchcompiler( name = "optimize_lib", tool = ":matchcompiler", deps = [":cppcheck"], prefix = "optimized_" # 添加前缀,确保输出路径有效 )
内容的提问来源于stack exchange,提问作者tenspd137
相关产品推荐
相关产品推荐

