Bazel构建:如何让Python依赖C++程序的输出?
问题描述
我有一个C++程序,通过Bazel的cc_library和cc_binary定义如下:
cc_library( name = "lib", srcs = ["src/utils.cpp", "src/api.cpp"], hdrs = ["include/header1.h", "include/header2.h", "include/header3.h", "include/header4.h"], deps = [] ) cc_binary( name = "run_app", srcs = ["src/app.cpp"], deps = [":lib"] )
app.cpp运行后会生成output.xml。我还写了一个Python程序读取该XML文件并处理生成PNG图,对应的Bazel目标定义在同一个BUILD文件中:
py_library( name = "py_lib", deps = [ requirement("matplotlib"), requirement("pillow"), requirement("numpy"), requirement("kiwisolver"), requirement("packaging"), requirement("pyparsing"), requirement("cycler"), requirement("python-dateutil"), requirement("six"), requirement("fonttools"), requirement("importlib-resources"), requirement("contourpy"), requirement("zipp") ] ) py_binary( name = "xml_to_graph", srcs = ["src/xml_to_graph.py"], data = [":run_app"], deps = [":py_lib"] )
目前我需要分四步完成整个流程:
bazel build run_app./bazel-bin/run_appbazel build xml_to_graph./bazel-bin/xml_to_graph
我知道可以用bash脚本实现一键执行,但想了解Bazel的标准实现方式是什么?
Bazel标准实现方案
Bazel中处理这种"构建二进制→运行生成中间文件→构建另一个二进制→运行生成最终产物"的流程,标准做法是使用genrule(生成规则)将整个流程串联起来,让Bazel自动处理依赖顺序和执行逻辑。
基础实现
在现有的BUILD文件中添加一个genrule目标,把run_app、xml_to_graph作为依赖,然后在命令中依次执行两个二进制文件,并声明最终产物:
genrule( name = "generate_graph", srcs = [":run_app", ":xml_to_graph"], outs = ["output.png"], cmd = """ # 运行C++程序生成output.xml $(location :run_app) # 运行Python程序处理XML生成PNG $(location :xml_to_graph) """, )
进阶优化(严谨路径管理)
如果run_app或xml_to_graph支持指定输入/输出路径,建议显式指定文件路径,让Bazel完全管理中间文件和最终产物,避免沙盒环境下的路径问题:
genrule( name = "generate_graph", srcs = [":run_app", ":xml_to_graph"], # 声明中间文件output.xml和最终产物output.png outs = ["output.xml", "output.png"], cmd = """ # 指定run_app输出到Bazel管理的路径 $(location :run_app) --output $(location output.xml) # 指定xml_to_graph读取Bazel管理的XML文件,输出到指定路径 $(location :xml_to_graph) --input $(location output.xml) --output $(location output.png) """, )
使用方式
执行单个Bazel命令即可完成整个流程:
bazel build :generate_graph
Bazel会自动完成以下操作:
- 构建
lib和run_app - 运行
run_app生成中间文件 - 构建
py_lib和xml_to_graph - 运行
xml_to_graph生成最终PNG
最终的output.png会生成在bazel-bin/output.png路径下。
优势
- 完全利用Bazel的增量构建特性:只有当源码(如
app.cpp、xml_to_graph.py)或依赖发生变化时,才会重新执行对应步骤 - 所有生成的文件都在Bazel的输出目录中,不会污染源码目录
- 单个命令完成全流程,符合Bazel的构建哲学
内容的提问来源于stack exchange,提问作者stochasticlover1
相关产品推荐
相关产品推荐

