原文出處:劉建文 | 學術半·IT歌·文(http://arttech.us)
cscope是神馬
cscope 是什麼東東?先看看官方定義:
“cscope is an interactive, screen-oriented tool that allows the user to browse through C source files for specified elements of code.”
簡譯並補充為:“cscope 是一支面向螢幕的(與面向行相對)互動式C原始碼瀏覽程式。它可以對C程式原始碼的元素(例如各種標號:變數,宏以及函數調用等)進行索引,提供簡單的字元查詢介面,使用者可根據【元素名】對其定義及引用進行查詢查看。”
以上是cscope的一個嚴格的完整定義,此定義表明cscope有兩個主要功能,第一是對C源碼檔案進行[符號索引];第二是提供簡單的查詢介面。如果你一般只使用像VIM這樣的進階工具編輯和閱讀源碼,完全可把cscope理解成產生源碼[符號引用資料庫]的工具。
一些重要的概念源檔案(source files)
源檔案指被cscope的C源碼檔案,源檔案的來源有幾個,
- 第一,預設目前的目錄(包括子目錄,使用-R參數);
- 第二,命令列輸入;
- 第三,源碼檔案清單(見下面定義);
- 第四,包含目錄。
這四種檔案源的簡單理解是,目錄是一集檔案;命令列是一個或幾個檔案;包含目錄是檔案內的檔案;檔案清單是給cscope一張檔案清單,讓cscope自己去找,是簡接的自定檔案。
既然搜尋的檔案來源有多種,當給cscope提供了多種來源時,搜尋源碼的次序也是以上次序。
包含目錄(include dir)
對於任何一個C源碼包含檔案,如果它不是絕對路經(以反斜線開始),並且不在[命令列輸入]中或[源碼檔案清單]中時,cscope將搜尋[cscope 包含目錄],此目錄由命令列參數-I或環境變數$INCDIR指定。
源碼檔案清單(list file)cscope.files
源碼檔案清單功能提高了cscope的靈活性,它讓cscope不限死搜尋一集相近的檔案,也不限死源檔案是C源碼。預設的源碼檔案清單是目前的目錄的 cscope.files,也可以通過-i參數自定。
符號引用資料庫 cscope.out
cscope的索引輸出是一個叫符號交叉引用檔案(symble cross-reference file)——cscope.out,名字內涵較深刻,但有點學術味,不太好記。此文簡化為[符號引用資料庫]。此資料庫格式如何,查詢原理怎樣,待究,資料庫名可使用參數-f自定。
使用cscope閱讀Linux的核心源碼
1.確定項目源碼位置,例如/home/kemin/linux-2.6.31;
2.選定儲存一個cscope資料(包括[源碼列表檔案]和[符號引用資料庫])位置,例如/home/kemin/cscope/linux_no_driver;對於相對固定的大項目,有必要這樣做。
3.如有必要,可先產生被Cscope索引的[源碼列表檔案],觸發Cscope針對這些檔案進行索引,而不是對目前的目錄樹進行全面索引。有兩種情況有必要這樣做:
第一,有選擇地對項目源碼檔案進行掃描,過濾掉不感興趣的代碼;例如過濾掉Linux源碼目錄下的文檔(doc)、指令碼(script)和驅動程式源碼檔案(driver)等:
LNX=/home/kemin/linux-2.6.31
cd /
find $LNX \
-path "$LNX/arch/*" ! -path "$LNX/arch/i386*" -prune -o \
-path "$LNX/include/asm-*" ! -path "$LNX/include/asm-i386*" -prune -o \
-path "$LNX/tmp*" -prune -o \
-path "$LNX/Documentation*" -prune -o \
-path "$LNX/scripts*" -prune -o \
-path "$LNX/drivers*" -prune -o \
-name "*.[chxsS]" -print >/home/jru/cscope/cscope.files
第二,項目為非C語言項目,檔案類型是.c, .h, .y, or .l 以外的。例如為java項目建立索引:
$ cd / ; find /my/project/dir -name '*.java' >/my/cscope/dir/cscope.files
注意 : 以上兩指令碼都是首先轉到根目錄(cd /)進行操作的,這樣做是為讓產生的[符號引用資料庫]對組建目錄沒有依賴,編輯程式可以任意目錄下運行,只要設定環境變數$CSCOPE_DB指向[符號引用資料庫]即可:
CSCOPE_DB=/foo/cscope.out; export CSCOPE_DB
特別地,如果過慮條件複雜,find很難編寫,你可以直接編輯cscope.files檔案。
4.產生[符號引用資料庫]cscope.out
如果是一個簡單的測試專案,則可以直接在源碼目錄執行:cscope 或 cscope -R然後調用編輯程式進行瀏覽,否則像本實驗那樣,轉到指定目錄進行操作:
$ cd /home/kemin/cscope/linux_no_driver # the directory with 'cscope.files'
$ cscope -b -q -k
三個參數的語義:
- The -b flag tells Cscope to just build the database, and not launch the Cscope GUI.
- The -q causes an additional, 'inverted index' file to be created, which makes searches run much faster for large databases.
- Finally, -k sets Cscope's 'kernel' mode--it will not look in /usr/include for any header files that are #included in your source files (this is mainly useful when you are using Cscope with operating system and/or C library source code, as we are here).
最後產生三個檔案:results in 3 files (cscope.out, cscope.in.out, and cscope.po.out)
5.cscope的使用
cscope 內建一個基於字元的查詢介面(Cscope GUI),當你在源碼目錄直接執行cscope時(無任何參數),Cscope 的預設行為是索引目前的目錄或cscope.files指定的源碼檔案,產生[符號引用資料庫]cscope.out(如果資料庫已經存在,則更新它),並調出Cscope GUI,選中查詢結果則調出由指定編輯程式(由$EDITOR指定,或者預設的vi)進行查看。-b參數只產生資料庫,-d參數則只調出Cscope GUI,不進行資料庫更新。
使用Cscope GUI是很原始的,最好配合一些進階的編輯程式使用,下面說說VIM。
配合VIM使用
1. 確定VIM版本,6.X以上並且編譯時間開啟了對Cscope 的支援,編譯開關是--enable-cscope
2. 下載並安裝指令檔cscope_maps.vim(http://cscope.sourceforge.net/cscope_maps.vim ),一般情況下只要把該拷貝到VIM安裝目錄的下子plugin目錄即可(可使用VIM命令:scriptename查看)。
3. 游標搜尋
Put the cursor over a C symbol ,
- 當前視窗搜尋
- Type "CTRL-\ s" (Control-backslash, then just 's') ,the '\' key is right next to the ']' key, which is used for ctags searches
- hit "CTRL-t" to jump back
- 分割視窗搜尋
- 水平分割: "CTRL-spacebar s"
- 垂直分割:CTRL-spacebar CTRL-spacebar s
4. 傳統命令列搜尋
- ":cscope find symbol foo" (or, more tersely, ":cs f s foo").
- To do the horizontal split version, use ":scscope" (or just ":scs")
5. 四種常用的搜尋目標類型
- 's', for 'find all uses of symbol X'.
- 'g' finds the global definition(s) of a symbol,
- 'c' finds all calls to a function,
- 'f' opens the filename under the cursor
6.6 VIM多視窗功能使用
- 在多個視窗間切換: 'CTRL-W w' (or CTRL-W arrow key, or CTRL-W h/j/k/l for left/up/down/right),
- 關閉當前視窗: 'CTRL-W c' (or good old ':q'),
- 關閉其它視窗: 'CTRL-W o',
- 分割當前視窗: 'CTRL-W s' (or 'CTRL-W v' for a vertical split),
- 在新視窗打一個檔案: ':spl[it] filename']