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

如何过滤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文件,移除不需要的节点和边。核心思路是:

  1. 识别并删除所有标签为*.c或*.o的节点行
  2. 删除所有涉及这些节点的边
  3. 保留可执行文件、库文件(.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 17:47:05