跳到主要內容

閱讀 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), 目前還算堪用

    回覆刪除

張貼留言

這個網誌中的熱門文章

(C/C++ ) 如何在 Linux 上使用自行編譯的第三方函式庫

以使用 LevelDB 為例。 抓好並編好相關檔案,編譯方式見第三方函式庫附的說明:$ ls include/ # header files leveldb/ $ ls out-shared/libleveldb.so* # shared library out-shared/libleveldb.so@ out-shared/libleveldb.so.1@ out-shared/libleveldb.so.1.20* 下面的例子用 clang++ 編譯,這裡用到的參數和 g++ 一樣。 問題一:找不到 header$ clang++ sample.cpp sample.cpp:5:10: fatal error: 'leveldb/db.h' file not found #include "leveldb/db.h" ^ 1 error generated. 解法:用 -I 指定 header 位置 問題二:找不到 shared library$ clang++ sample.cpp -I include/ /tmp/sample-2e7dd8.o: In function `main': sample.cpp:(.text+0x1e): undefined reference to `leveldb::Options::Options()' sample.cpp:(.text+0x6f): undefined reference to `leveldb::DB::Open(leveldb::Options const&, std::string const&, leveldb::DB**)' sample.cpp:(.text+0x10c): undefined reference to `leveldb::Status::ToString() const' sample.cpp:(.text+0x7d0): undefined reference to `leveldb::Status::ToString() const' clang: error: linker command failed with exit code 1 (u…

熟悉系統工具好處多多

記一下以前很困擾, 現在秒殺的小事。 更新這篇的時候, 忘了函式庫用的 man page 裝在那個 package。以前就會想辦法 google, 運氣好一下會找到, 運氣不好會多找一會兒。 這回我想到新作法:$ strace -e open man 3 printf > /dev/null # 發現是讀 /usr/share/man/man3/printf.3.gz $ dpkg --search /usr/share/man/man3/printf.3.gz # 找到套件名稱 manpages-dev $ aptitude show manpages-dev # 確認描述符合, 收工

virtualbox 使用 USB 裝置

2012-12-16 更新 現在 (4.x 版) 似乎無需做任何設定, 只要有裝 Oracle VM VirtualBox Extension Pack, 在 VirtualBox 視窗右下角按 USB 的圖示, 再點目標裝置, 即可加入或移除該裝置 同一時間只有 host 或 guest 可擁有該裝置, 所以從 guest OS 移除, 相當於接回 host OS 目前 VirtualBox 只支援 USB 2.0 的插槽, 若偵測不到時, 注意一下是否為這個問題 有時拔拔插插, VirtualBox 會進入奇怪的狀態, 接上去 guest OS 無法連接且跳出 device is busy 的錯誤訊息。試看看拔除該裝置, 重開 guest OS (續上則) 若重開 guest OS 無效, 並且 host OS 已移除該裝置, VirtualBox 的 USB 清單卻仍顯示 "captured", 試看看拔除該裝置, 重開 host OS原文網路上搜一下, 比較多是 Ubuntu 當 host 的解法, 我的情況是 Win7 當 host, Ubuntu 當 guest。 這兩篇說明很詳細《Learn How to Set Up USB and Networking Options in VirtualBox》《幻影千瞳的部落格: VirtualBox 使用筆記(二):使用 USB 裝置》 現在的版本圖形介面很好用了, 不用像第二篇說的那樣用指令操作。這裡記下我的操作步驟: 關掉 guest OS 在 VirtualBox 選單, 選擇 guest OS -> Settings -> USB -> Enable USB 2.0 會出現訊息框, 說明要安裝 Oracle VM VirtualBox Extension Pack。下載後安裝它 host OS 插入 USB 隨身碟 在 VirtualBox 選單, 選擇 guest OS -> Settings -> USB, 點右邊有綠色 "+" 的 USB 頭的圖示, 選擇該 USB 隨身碟, 加入它的 filter 從 host OS 移除 USB 隨身碟 開啟 guest OS 插入 USB 隨身碟, 於是 guest OS 會自動偵測…