閱讀 C/C++ 原始碼的好幫手

最近有需求讀 C/C++ 的東西, 試了 ctags, cscope 覺得不理想。問了一下收到許多回應 (G+plurk ), 真是太感謝大家了, 減少入門摸索的時間。

試用的感想如下:

grep

  • 優點: 好上手
  • 缺點: 陽春
  • 安裝: 內建於 Linux

gtags

  • 優點: 可找 caller 和 callee
  • 缺點: 因為索引檔是由 ctags 來的, 會漏東西; 執行方式也有些不便
  • 安裝: 程式很久沒人更新了, 要做一些修正才裝得起來
    • 參照官網指示
    • make 時看少了什麼 header, 手動補一下 header
    • 然後 make 還是會失敗, 將 gas.py 的 "import as" 改為 "import asm", 下面用到的模組名也要跟著改, as.py 也要改為 asm.py。python 2.6 後 as 是 keyword
    • 編好後將幾個用到的 python scripts 第一行由 python2.4 改為 python

ack

  • 優點: 比 grep 容易使用, 省得配合一些 command 過濾檔案, 見官網的《Top 10 reasons to use ack instead of grep.》。而且還有彩色的輸出!!
  • 缺點: 因為沒建 index 的關係, 速度較 id-utils 慢, 我的測試情境要 3s, 而 id-utils 只要 0.006s
  • 安裝: curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

id-utils

  • 優點: 速度快, 和測 ack 同樣的情況, 建索引 5.3s, 之後搜尋瞬殺
  • 缺點: 介面沒有 ack 直覺易用, 我寫了個小程式 gj 以 id-utils 為底, 提供彩色輸出和進一步過濾檔名的功能。
  • 安裝: Ubuntu 超容易, aptitude install id-utils

Eclipse CDT

  • 優點: 方便開新視窗看 caller、callee
  • 缺點: 不方便搭 vim 使用 (對 vim 重度使用者才有差); 建 index 有點久, 我的測試情境要數分鐘到十分鐘吧
  • 安裝: 結果這個是我試最久的, 因為不知怎麼建 index。參考官網 FAQ, 建索引前要先設 include dir path。我一直找不到 context menu, 結果它就是左側的那個專案清單。另外 Eclipse CDT 也會漏一些東西, C++ 特別嚴重。

結論

  • 用 Eclipes CDT 方便平時快速跳到定義
  • 輔以 id-utils + gj 確保不會漏東西。之後用一用再視需求來更新 gj 功能。

2011-12-16 Update

Eclipse CDT 的問題有一部份是我設錯, 詳細設法見用 Eclipse CDT 讀 C/C++ 原始碼

2012-02-02 Update

留言

  1. 以需要能找出全部有用到某函式的地方為前提:
    1. 純粹 C 而不是 C++ 的 code base, cscope + VIM plugin 很好用
    2. Eclipse 與 VIM 見 Vrapper:http://itrs.tw/wiki/IDEs_with_VIM_Emulation

    要在 VIM 中方便跳到 search results,我有個奇怪用法:
    1. 將 search result 轉成『grep -n 格式』存在檔案 l 中
    2. vim
    3. :set grepprg=cat\ l
    4. :grep
    5. :copen

    回覆刪除
  2. 之前讀 python code 時有用過 pycscope + VIM plugin, 相當不錯, 原以為 cscope + VIM plugin 也可適用, 可惜 C++ 的情況滿多不適用的。

    http://vrapper.sourceforge.net/features/
    沒想到 vrapper 有支援 macro, 這樣應該可用, 明天來試試。很久以前用過類似的東西, 但沒有 macro 用起來不順手

    最後的例子沒看懂, 是指要先在 cmd line 用 grep -n 將輸出導到檔名 "|" 中, 再做後面的操作嗎??

    回覆刪除
  3. Re: 最後的例子沒看懂

    若搜群工具可以輸出 "FILE:LINE:...SNIPPET.." 格式,將結果存於檔案中, 再用以上設定在 VIM 中打開就可以像在 VIM 中用內建 grep 一樣,跳到各搜尋結果。

    搜尋工具格式不同,則寫 script 或手動轉。
    VIM 也有 "grepformat" 參數,但我自己是用上述方法。

    回覆刪除
  4. 為了主題完整性,跟之後讀者分享 grep 顏色輸出設定:

    alias egrep='egrep --color=tty -d skip'
    alias egrpe='egrep --color=tty -d skip'
    alias fgrep='fgrep --color=tty -d skip'
    alias fgrpe='fgrep --color=tty -d skip'
    alias grep='grep --color=tty -d skip'
    alias grpe='grep --color=tty -d skip'

    以上可安全的加在 .bashrc 中,
    grep 發現 stdout 不是 tty 時就會改回無顏色控制碼的輸出。
    來源 glibc maintainer Ulrich Drepper:
    http://udrepper.livejournal.com/17109.html

    回覆刪除
  5. 跟ack一樣的功能,不過用Python寫成,程式碼也蠻易讀。
    http://eli.thegreenplace.net/2011/10/14/announcing-pss-a-tool-for-searching-inside-source-code/

    回覆刪除
  6. Eclipse漏東西是什麼情況? 試試看把indexer的cache limit調大一點...
    By the way, gj還不錯用!! Good Job~XD

    回覆刪除
  7. 還有一個東西叫 lxr,
    http://lxr.sourceforge.net/
    我覺得也滿好用的溜

    回覆刪除
  8. @scw 謝啦, 看起來頗強大的, 明天來試試, 好像是類似 doxygen 的工具?

    回覆刪除
  9. 較新的 lxr 替代品是 dxr:
    http://dxr.mozilla.org/mozilla/index.html
    是以 Clang 為基礎的:
    https://github.com/mozilla/dxr

    @fcamel: "lxr 好像是類似 doxygen 的工具?"
    lxr, Linux Cross Reference, 原本是為了研究 Linux Kernel source code 而寫出來的。至今討論 Linux Kernel 內部 API 時還是很常用。

    回覆刪除
    回覆
    1. lxr or doxygen is too slow. I like to use idutils.

      刪除
  10. 我使用你提供的 gj 我發現有些關鍵字還是沒有找到
    grep 但用可以找到~ 請問這是什麼原因?
    謝謝

    回覆刪除
  11. gj 底層是 id-utils,
    我用預設的方式建 index, 似乎只有建 C/C++, ASM, Java,
    有些語言不會有建 index

    另外我是用預設的方式找 symbol,
    要完全符合才會找出來, 沒有模糊比對

    回覆刪除
    回覆
    1. $ cat mkid-typemap
      *.idl text
      *.ipdl text
      *.cpp text
      *.h text
      *.c text
      *.js text
      *.jsm text
      *.in text
      *.mk text
      $ mkid -m mkid-typemap

      刪除
  12. GNU Global 跟這些工具比較不知如何呢?

    回覆刪除
  13. 有人用 C 寫了一個類似 ack 的工具,叫 ag,作者宣稱快三到五倍。
    https://github.com/ggreer/the_silver_searcher

    回覆刪除
  14. id-utils 效率很好 (十倍以上的效能), 對大型專案來說, 滿需要這種等級的效能。我在上層包了一層介面 (gj), 目前還算堪用

    回覆刪除

張貼留言

這個網誌中的熱門文章

virtualbox 使用 USB 裝置

熟悉系統工具好處多多

如何 git merge 更改檔名的檔案