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

如何从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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:04:53