大家都知道, Doxygen 可以用于提取代码的注释生成项目的文档,只要注释满足它规定的格式。我喜欢通过它生成类继承图(inheritance diagram)和函数调用图(callgraph),有了他们能够加快对代码的理解。
以 MySQL 代码为例, Doxygen 生成的类继承图和调用图分别是这样的:
之前工作中交接了几个 C++ 项目,由于还不熟悉代码,就想用 Doxygen 来生成这两种图来加快熟悉代码,但结果却生成失败了。
而一个普通的 hello world 程序却没有问题,说明是 Doxygen 对特定的代码处理有 bug 。
几经排查,最后发现只要代码中包含2个以上的 using namespace xxx;
语句,调用图就无法生成。比如下面这样一个简单的类实现,就无法生成调用关系图。
虽然这种直接包含命名空间的用法不推荐,但是在已有项目中却很常见,这样的话 Doxygen 基本就不可用了。
由于当时没有时间,就先给官方报了一个 issue ,等待他们解决。
没想到几个月之后,官方也还没有解决。而最近正好有点时间,就重新去分析这个 bug ,看如何解决。
解决过程虽然花了不少时间,但总结起来有几点:
- 缩小范围:对比正常生成调用图和无法生成调用图的两种情况下的 stdout 输出,再根据差异信息 grep 定位到生成 callgraph 图的相关代码;
- 添加 printf 调试信息,找出 callgraph 元数据的来源,即 Doxygen 怎么得到调用关系的;
最终找到这部份实现在
code.l
(C族语言的 Flex 实现,用于解析工程源码)中, Doxygen 基于 Flex 实现了自己的词法解析; - 学习 Flex 的使用方法;
最后终于找到问题的根源在于, Doxygen 在解析 using namespace xxx;
指令的时候,错误地认为文件中往后的代码属于 xxx 命名空间( pushScope
),从而把函数的绝对命名空间弄错,就没法解析出正确的调用关系了。
提了 PR 修复了之后,前面的测试代码就能正确地生成如下的函数调用图了。
Updates:
- 2021.02 这个 PR 已经合并到 master 了,但是还没有发布,需要再等一等。
- 2021.08.19 发布的 版本 1.9.2,已经包含了这个 bugfix 。