最可行方案是用 clang++ 编译并基于 compile_commands.json 与 clang ast 工具链(如 clang-query、castxml)提取调用边;必须生成绝对路径的 compile_commands.json,先验证 callexpr 是否正确识别目标调用,再剪枝可视化。

用 clang++ + clang-tools 生成调用图最可行
直接靠 C++ 标准编译器(如 g++)无法生成调用图——它不记录函数间调用关系。真正能落地的方案是基于 Clang 的静态分析能力,用 clang++ 编译时加 -emit-ast 或结合 clang-query/clang-tool 提取调用边。Clang AST 比 GCC 的更规范、工具链更成熟,尤其适合做跨函数/跨文件的调用关系挖掘。
- 必须用
clang++编译,不能用g++——GCC 没公开稳定的 AST 接口供外部工具消费 - 项目需能被 Clang 正确解析(头文件路径、宏定义、C++ 标准版本要对齐,常见坑是
-std=c++17没传给 Clang 工具链) - 推荐先用
compile_commands.json描述构建过程,这是clang-tools类工具的统一输入格式,避免手写参数出错
生成 compile_commands.json 是前提,别跳过
没有 compile_commands.json,几乎所有自动化调用图工具都会失效。这不是可选步骤,而是 Clang 工具链识别 include 路径、宏、语言标准的唯一可靠方式。
- CMake 项目:加
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON重新 configure,会自动生成该文件 - 非 CMake 项目:可用
bear --make或intercept-build make拦截编译命令生成,但要注意拦截时不能有并行(make -j)否则会漏命中断言 - 验证是否有效:打开
compile_commands.json,检查每条记录里file字段是相对路径还是绝对路径;Clang 工具默认只认绝对路径,若为相对路径需用jq或脚本批量补全
用 castxml 或 clang-ast-dump 快速验证调用结构
别一上来就跑完整调用图工具。先确认 AST 能正确提取出你关心的调用点,比如 foo() 是否真被 bar() 调用,避免后期白忙。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 用
clang++ -Xclang -ast-dump -fsyntax-only main.cpp看 AST 输出,搜索CallExpr节点,确认目标调用被识别为表达式而非宏展开或模板推导结果 - 更稳的方式是用
castxml(基于 Clang 的 C++ 到 XML 转换器):执行castxml --castxml-output=1 --castxml-cc-gnu g++ main.cpp生成 XML,再用 XPath 查//FunctionRef[@name="foo"]的父节点是否为CallExpr - 注意:模板实例化函数(如
std::vector<int>::push_back</int>)在 AST 中名字带空格或嵌套符号,直接搜函数名容易漏,建议先 dump 出所有CallExpr再过滤
用 CodeCity 或 callgraph.py 做可视化,但得手动剪枝
原始调用边数量爆炸(尤其含 STL、Boost),直接渲染全是噪音。真正可用的交互式图必须做三层剪枝:按源文件过滤、按调用深度限界、按函数命名空间白名单。
-
callgraph.py(来自 LLVM 示例)能从compile_commands.json生成 DOT 文件,但默认输出包含所有隐式调用(如构造函数、operator=),加--no-implicit参数才能聚焦显式调用 - CodeCity 风格的 3D 可视化(如
cpp-dependencies工具)需要把调用频次映射为建筑高度,但它的“频次”其实是边数,不是运行时统计——别误以为是性能热点图 - 最实用的组合:用 Python +
pydot读取 DOT,删掉std::和boost::开头的节点,再按main.cpp为根做 BFS 限制深度 ≤3,最后导出 SVG 支持浏览器缩放和点击跳转源码行号
调用图真正的复杂点不在生成,而在“哪些边该保留”。没做过源码域划分和业务逻辑分层的项目,图里一半节点你根本不知道属于哪个模块。动手前先花十分钟划出核心类/主流程函数,再反向提取它们的上游调用者,比全量图有用得多。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










