最近需要讀比較複雜 C++ 程式, 常常看到一堆 class 有個祖宗十八代, 要找出眾多子代的 class 或是某個 method 到底是那一代祖先實作的, 有些麻煩。
原本想自己玩看看 clang, 用 clang 分析原始碼產生 graph, 再套 graphviz 畫出來。轉念一想, 這麼常見的需求, 應該有人做好了。況且, 自己處理單檔可能不會麻煩, 但若多個檔案需要不同 include path (-I) 時, 到也有些頭痛。
上網查一下, 發覺 stackoverflow 有人推薦用 doxygen, 一試就靈, 最棒的是 doxygen 不需另外讀編譯 C/C++ 的設定檔, 它直接讀取指定的目錄。先跑 doxygen -g myconfig 產生設定檔 myconfig, 再修改 myconfig:
- INPUT
- RECURSIVE = YES
最後執行 doxygen myconfig 即可。
產生的網頁裡可看到各個 class 的祖譜, 非常方便。我猜 doxygen 可能是直接做文字分析, 不是用 compiler 下手。
實測的結果也的確有問題, Ubuntu 12.04 的 doxygen 有點舊, class 有用到 C++11 的 keyword final 時, final 反而會被當成 class name。幸好在 doxygen 1.8.2 版已解決, 先裝 doxygen 舊版, 再自己抓原始碼編譯, 用 checkinstall 封裝成 package 即可解掉這問題。
用 checkinstall 封裝的好處是, 可從 dpkg -L PKG_NAME 看裝的內容, 日後有問題也可用 dpkg -r PKG_NAME 刪除。
Btw, doxygen 參數一堆, 有閒再來研究看看有什麼好用的東西。
2013-09-10 更新
若遇到 macro 造成 doxygen 分析錯誤, 可試著要求 doxygen 展開特定的 macro。作法是修改下列的設定:
- ENABLE_PREPROCESSING = YES
- MACRO_EXPANSION = YES
- EXPAND_ONLY_PREDEF = YES
- PREDEFINED = ABC=xyz
- EXPAND_AS_DEFINED = ABC
其中 EXPAND_AS_DEFINED 填入希望展開的 macro。若執行後沒有展開成功, 可以設 PREDEFINED 告知 doxygen 如何展開目標 macro。見 Doxygen Manual: Preprocessing 了解和其它前處理相關的設定。
沒有留言:
張貼留言