如何过滤Ninja生成的Dot文件,仅保留库与可执行文件?
问题描述
我有一个基于Meson的项目,可通过命令:
ninja -t graph myExecutable | dot -Tpng -ograph.png
生成Dot格式的依赖图文件及对应的PNG图像。现在希望过滤该Dot文件,移除所有*.c源文件与*.o目标文件的相关节点和边,仅保留库文件与可执行文件的依赖关系,请问是否可以实现?
待过滤的Dot文件示例:
digraph ninja { rankdir="LR" node [fontsize=10, shape=box, height=0.25] edge [fontsize=10] "0x55f191f3ea60" [label="myexec"] "0x55f191f3e9f0" [label="c_LINKER", shape=ellipse] "0x55f191f3e9f0" -> "0x55f191f3ea60" "0x55f191f3e6a0" -> "0x55f191f3e9f0" [arrowhead=none] "0x55f191f3d5d0" -> "0x55f191f3e9f0" [arrowhead=none] "0x55f191f3e6a0" [label="myexec.p/src_myexec.c.o"] "0x55f191f3e730" -> "0x55f191f3e6a0" [label=" c_COMPILER"] "0x55f191f3e730" [label="../src/myexec.c"] "0x55f191f3d5d0" [label="subprojects/mylib/libmylib.so.p/libmylib.so.symbols"] "0x55f191f3d6d0" -> "0x55f191f3d5d0" [label=" SHSYM"] "0x55f191f3d6d0" [label="subprojects/mylib/libmylib.so"] "0x55f191f3d220" -> "0x55f191f3d6d0" [label=" c_LINKER"] "0x55f191f3d220" [label="subprojects/mylib/libmylib.so.p/src_library.c.o"] "0x55f191f3d320" -> "0x55f191f3d220" [label=" c_COMPILER"] "0x55f191f3d320" [label="../subprojects/mylib/src/library.c"] }
解决方案
完全可以实现,你可以通过**文本处理工具(如sed或awk)**过滤Dot文件,移除不需要的节点和边。核心思路是:
- 识别并删除所有标签为
*.c或*.o的节点行 - 删除所有涉及这些节点的边
- 保留可执行文件、库文件(
.so/.a等)以及链接器相关的节点和边
方法一:使用sed脚本过滤
运行以下命令直接生成过滤后的Dot文件,再转成PNG:
ninja -t graph myExecutable | sed -E ' # 收集要删除的节点ID:标签是*.c或*.o的节点 /label=".*\.(c|o)"/ { s/^"([0-9a-fx]+)".*/\1/ H d } # 删除涉及已收集节点的边 /->/ { G s/^"([0-9a-fx]+)".*\n(.*)/\1|\2/ :loop s/([0-9a-fx]+)\|.*\1// t loop s/\|.*// /./!d } ' > filtered_graph.dot # 转成PNG dot -Tpng filtered_graph.dot -ograph_filtered.png
方法二:使用awk脚本过滤(更易读)
如果sed的写法太复杂,可以用awk实现:
ninja -t graph myExecutable | awk ' BEGIN { delete_nodes = "" } # 标记要删除的节点ID /label=".*\.(c|o)"/ { match($0, /^"([0-9a-fx]+)"/, id) delete_nodes[id[1]] = 1 next } # 过滤涉及删除节点的边 /->/ { match($0, /^"([0-9a-fx]+)" -> "([0-9a-fx]+)"/, ids) if (delete_nodes[ids[1]] || delete_nodes[ids[2]]) { next } } # 保留其他行 { print } ' > filtered_graph.dot dot -Tpng filtered_graph.dot -ograph_filtered.png
效果说明
针对你提供的示例Dot文件,过滤后会保留以下内容:
digraph ninja { rankdir="LR" node [fontsize=10, shape=box, height=0.25] edge [fontsize=10] "0x55f191f3ea60" [label="myexec"] "0x55f191f3e9f0" [label="c_LINKER", shape=ellipse] "0x55f191f3e9f0" -> "0x55f191f3ea60" "0x55f191f3d5d0" -> "0x55f191f3e9f0" [arrowhead=none] "0x55f191f3d5d0" [label="subprojects/mylib/libmylib.so.p/libmylib.so.symbols"] "0x55f191f3d6d0" -> "0x55f191f3d5d0" [label=" SHSYM"] "0x55f191f3d6d0" [label="subprojects/mylib/libmylib.so"] }
最终生成的PNG会只显示可执行文件myexec、链接器、库文件libmylib.so以及它们之间的依赖关系。
内容的提问来源于stack exchange,提问作者Mariano
相关产品推荐
相关产品推荐

