簡介
cscope是一款用于浏覽C源碼的工具,類似于ctags,但強大得多。
下文以leveldb代碼庫為例,講述cscope的使用方法。
建立cscope資料庫
在代碼庫的根目錄下執行:
$ cscope -Rbq
将産生cscope.out、cscope.in.out和cscope.po.out三個檔案。
各個選項的含義如下:
-b:僅建構交叉引用(cross-reference)檔案,即資料庫,然後退出,而不會進入下面的互動界面:

-R:遞歸解析所有的子目錄。
-q:通過反向索引加速符号的查找過程。該選項會導緻cscope額外産生cscope.in.out和cscope.po.out兩個檔案。
$ file cscope.out
cscope.out: cscope reference data version 15 with inverted index
相關指令
所有的cscope指令都以:cscope(:cs)開頭。:表示這些指令均在vim的一般模式下執行。
以下逐一介紹cscope的子指令。
add(增加一個新的cscope資料庫/連接配接)
用法
:cs add {file|dir} [pre-path] [flags]
例子
# 目前在./table目錄,把根目錄下的cscope.out加進來:
:cs add ../cscope.out /home/xhb/code/os/test-leveldb/leveldb-master -C
# 此時執行查找操作,會得到兩個比對項:
# /home/xhb/code/os/test-leveldb/leveldb-master/include/leveldb/table_builder.h
# /home/xhb/code/os/test-leveldb/leveldb-master/table/table_builder.cc
比對項中的/home/xhb/code/os/test-leveldb/leveldb-master即為add指定的pre-path參數,而-C指定了搜尋時忽略大小寫。
如果不指定pre-path呢?
:cs add ../cscope.out
# 則查找結果就是:
# include/leveldb/table_builder.h
# table/table_builder.cc
如果目前目前下有cscope.out檔案,則打開vim時會自動加載該資料庫。
隻有把cscope資料庫加到vim中,才能進行後續的find操作。
find(查找)
cs find {querytype} {name}
querytype(!!)
0或s:查找這個(指name參數,下同)C符号。
1或g:查找這個定義。
2或d:查找被這個函數調用的函數。
3或c:查找調用該函數的函數。
4或t:查找這個文本字元串。
6或e: 查找這個egrep的pattern。
7或f:查找這個檔案。
8或i:查找#include了這個檔案的所有檔案。
除了4和6,其他類型下的name參數前面的空格都被忽略。
如果比對項隻有一個,則直接跳轉到那裡;如果有多個,則可以選擇跳到哪一個。
查找檔案名中包含builder的檔案:
:cs find f builder
# 結果如下:
Cscope tag: builder
# line filename / context / line
1 1 db/builder.cc <<<unknown>>>
2 1 db/builder.h <<<unknown>>>
3 1 include/leveldb/table_builder.h <<<unknown>>>
4 1 table/block_builder.cc <<<unknown>>>
5 1 table/block_builder.h <<<unknown>>>
6 1 table/table_builder.cc <<<unknown>>>
對于#include的頭檔案,如果在目前目錄下找不到,cscope甚至會搜尋标準目錄(/usr/include/等)。比如:
:cs find f stdlib.h
# 結果如下:
Cscope tag: stdlib.h
# line filename / context / line
1 1 /usr/include/stdlib.h <<<unknown>>>
2 1 /usr/include/bits/stdlib.h <<<unknown>>>
基于目前光标所在處的單詞進行查找:
# 目前光标停留在filter_policy上
:cs find f <cfile>
# 直接跳轉到include/leveldb/filter_policy.h
# 目前光标停留在WriteBlock上
:cs find t <cword>
# 效果等同于:cs find t WriteBlock
其他輔助用法
Ctrl-t(!!)
假設A調用了B,B調用了C,我們剛開始在A處,通過:cs find g B跳到了B的定義,再跳到了C的定義,則通過Ctrl-t,我們可以回到B,再回到A。這裡實際上維護了一個棧。
:scscope(:scs)(!!)
與:cs做的事情一樣,但它會有分屏的效果。
# 水準分屏
:scs find f block_builder.cc
# 垂直分屏
:vert scs find f table_builder.cc
對于多個分屏的視窗,常用的操作有:
Ctrl-w Ctrl-w:在不同視窗間跳轉。
hide:關閉目前視窗。
only:僅保留目前視窗。
show(顯示所有的cscope連接配接)
:cs show
# 結果如下:
# pid database name prepend path
0 8380 cscope.out <none>
8380為cscope程序的ID,通過ps可以看到vim程序為cscope程序的父程序,通過lsof可以看到它們之間通過pipe通信。
kill(斷開cscope連接配接)
:cs show
# 結果如下:
# pid database name prepend path
0 8380 cscope.out <none>
# 則可以這樣斷開該連接配接:
:cs kill 0
# 而斷開全部連接配接是這樣:
:cs kill -1
reset(重新初始化所有cscope連接配接)
cscope選項
使用:set設定所有的選項。理想的做法是在啟動檔案(如.vimrc)中做這件事,因為一些cscope變量隻在.vimrc中有效,vim啟動後再設定它們将沒有效果。
cscopeprg(csprg)
指定執行cscope的指令,預設就是"cscope"。比如:
:set csprg=/usr/bin/cscope。
cscopequickfix(csqf)
是否使用quickfix視窗顯示cscope的結果。需要在編譯vim時指定+quickfix,才能啟用該選項。預設值為""。
比如:set cscopequickfix=s-,c-,d-,i-,t-,e-,s/c/d/i/t/e即:cs find的querytype,其後的标志可以有+(将結果追加到quickfix視窗)、-(清空上一次的結果)、0(不使用quickfix。這裡對于querytype=f,沒有指定也相當于标志為0)。
對于querytype=f,不指定标志時:
:set cscopequickfix=s-,c-,d-,i-,t-,e-
# 沒有對querytype=f指定使用quickfix視窗,是以:cs find f builder的結果以位置清單(location list)的方式顯示
Cscope tag: builder
# line filename / context / line
1 1 builder.cc <<<unknown>>>
2 1 builder.h <<<unknown>>>
3 1 table_builder.h <<<unknown>>>
4 1 block_builder.cc <<<unknown>>>
5 1 block_builder.h <<<unknown>>>
6 1 table_builder.cc <<<unknown>>>
對于querytype=f,指定标志為-時:
:set cscopequickfix=s-,c-,d-,i-,t-,e-,f-
# 此時執行:cs find f builder,在vim視窗底部會顯示:
(1 of 6): <<<unknown>>>
使用quickfix視窗的好處是,可以在搜尋結果的多個比對項間進行跳轉,而位置清單的方式則隻能選擇一個項。
關于多個quickfix視窗的指令,常用的如下(!!):
:cnext/:cn:切換到下一個。
:cprev/:cp:切換到上一個。
:clist:列出所有項。
:cr:切換到第一個。
:cla:切換到最後一個。
對于querytype=f,指定标志為+時:
:set cscopequickfix=s-,c-,d-,i-,t-,e-,f+
# 則:cs find f builder每次的結果都會“累加”,比如執行10次就會有6*10=60個比對項
cscopetag(cst)
設定之後,:tag/Ctrl-]/vim -t将使用:cstag,而不是預設的:tag,即cscope資料庫和tag檔案均用于搜尋。
:set cst # :set nocst(預設)
在cscope資料庫中搜尋時,:cstag和:cs find g等價;在tag檔案中搜尋時,:cstag和:tjump等價。
cscopetagorder/csto
指定:cstag的搜尋順序。0表示先搜尋cscope資料庫,若不比對,再搜尋tag檔案,1則相反。
:set csto=1 # 預設為0
cscopeverbose/csverb
若不設定(預設),則增加cscope資料庫時,将不會列印成功或失敗資訊。
:set csverb
:set nocsverb
cscopepathcomp/cspc
指定在查找結果中顯示多少級檔案路徑。預設值0表示顯示全路徑(不是linux系統的全路徑,比如如果沒有設定pre-path,則block_builder.cc的全路徑是table/block_builder.cc),1表示隻顯示檔案名,等等。
例子:
:set cspc=3
# :cs find f table_builder的查找結果:
Cscope tag: table_builder
# line filename / context / line
1 1 include/leveldb/table_builder.h <<<unknown>>>
2 1 table/table_builder.cc <<<unknown>>>
:set cspc=1
# :cs find f table_builder的查找結果:
Cscope tag: table_builder
# line filename / context / line
1 1 table_builder.h <<<unknown>>>
2 1 table_builder.cc <<<unknown>>>
快捷鍵映射
TODO
參考資料
- vim(7.2) :help cscope
- cscope man page
- http://cscope.sourceforge.net/
- https://www.cs.oberlin.edu/~kuperman/help/vim/windows.html