1. 参考资料
参考资料:
2. 要点
baidu之后,发现有3点:
- ctags:可以ctags --version检查本机上安装的ctags是否为下面这个版本,本文接下来的示例即以此ctags进行演练
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$ ctags --version Exuberant Ctags 5.9~svn20110310, Copyright (C) 1996-2009 Darren Hiebert Compiled: Nov 9 2011, 17:40:39 Addresses: <dhiebert@users.sourceforge.net>, http://ctags.sourceforge.net Optional compiled features: +wildcards, +regex flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$
- cscope
- taglist
3. ctags
当然,要学会游泳,最好的方式就是下水。所以,这里就通过一系列的命令熟悉整个环境。
3.1 建立tags文件
先用最简单的方式进行实践,比如用ctags -R .对当前目录下的文件生成tags文件。
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$ ll
总用量 368
drwxr-xr-x 4 flying-bird flying-bird 4096 6月 22 10:31 ./
drwxrwxr-x 8 flying-bird flying-bird 4096 6月 18 22:20 ../
-rw-rw-r-- 1 flying-bird flying-bird 1514 6月 18 19:01 Android.mk
-rw-rw-r-- 1 flying-bird flying-bird 1154 6月 18 19:01 Asec.h
-rw-rw-r-- 1 flying-bird flying-bird 2227 6月 18 19:01 CleanSpec.mk
-rw-rw-r-- 1 flying-bird flying-bird 23457 6月 18 19:01 CommandListener.cpp
-rw-rw-r-- 1 flying-bird flying-bird 2466 6月 18 19:01 CommandListener.h
-rw-rw-r-- 1 flying-bird flying-bird 65366 6月 18 19:01 cryptfs.c
-rw-rw-r-- 1 flying-bird flying-bird 5680 6月 18 19:01 cryptfs.h
-rw-rw-r-- 1 flying-bird flying-bird 8518 6月 18 19:01 Devmapper.cpp
-rw-rw-r-- 1 flying-bird flying-bird 1270 6月 18 19:01 Devmapper.h
-rw-rw-r-- 1 flying-bird flying-bird 15543 6月 18 19:01 DirectVolume.cpp
-rw-rw-r-- 1 flying-bird flying-bird 2767 6月 18 19:01 DirectVolume.h
-rw-rw-r-- 1 flying-bird flying-bird 2674 6月 18 19:01 Ext4.cpp
-rw-rw-r-- 1 flying-bird flying-bird 894 6月 18 19:01 Ext4.h
-rw-rw-r-- 1 flying-bird flying-bird 6943 6月 18 19:01 Fat.cpp
-rw-rw-r-- 1 flying-bird flying-bird 1138 6月 18 19:01 Fat.h
-rw-rw-r-- 1 flying-bird flying-bird 4679 6月 18 19:01 fstrim.c
-rw-rw-r-- 1 flying-bird flying-bird 723 6月 18 19:01 fstrim.h
drwxrwxr-x 8 flying-bird flying-bird 4096 6月 18 19:01 .git/
-rw-rw-r-- 1 flying-bird flying-bird 2525 6月 18 19:01 hash.h
-rw-rw-r-- 1 flying-bird flying-bird 7524 6月 18 19:01 Loop.cpp
-rw-rw-r-- 1 flying-bird flying-bird 1294 6月 18 19:01 Loop.h
-rw-rw-r-- 1 flying-bird flying-bird 5063 6月 18 19:01 main.cpp
-rw-rw-r-- 1 flying-bird flying-bird 1440 6月 18 19:01 NetlinkHandler.cpp
-rw-rw-r-- 1 flying-bird flying-bird 949 6月 18 19:01 NetlinkHandler.h
-rw-rw-r-- 1 flying-bird flying-bird 2673 6月 18 19:01 NetlinkManager.cpp
-rw-rw-r-- 1 flying-bird flying-bird 1247 6月 18 19:01 NetlinkManager.h
-rw-rw-r-- 1 flying-bird flying-bird 6542 6月 18 19:01 Process.cpp
-rw-rw-r-- 1 flying-bird flying-bird 1439 6月 18 19:01 Process.h
-rw-rw-r-- 1 flying-bird flying-bird 1334 6月 18 19:01 ResponseCode.cpp
-rw-rw-r-- 1 flying-bird flying-bird 2865 6月 18 19:01 ResponseCode.h
drwxrwxr-x 2 flying-bird flying-bird 4096 6月 18 19:01 tests/
-rw-rw-r-- 1 flying-bird flying-bird 4249 6月 18 19:01 vdc.c
-rw-rw-r-- 1 flying-bird flying-bird 732 6月 18 19:01 VoldCommand.cpp
-rw-rw-r-- 1 flying-bird flying-bird 839 6月 18 19:01 VoldCommand.h
-rw-rw-r-- 1 flying-bird flying-bird 819 6月 18 19:01 VoldUtil.c
-rw-rw-r-- 1 flying-bird flying-bird 810 6月 18 19:01 VoldUtil.h
-rw-rw-r-- 1 flying-bird flying-bird 19816 6月 18 19:01 Volume.cpp
-rw-rw-r-- 1 flying-bird flying-bird 3328 6月 18 19:01 Volume.h
-rw-rw-r-- 1 flying-bird flying-bird 48540 6月 18 19:01 VolumeManager.cpp
-rw-rw-r-- 1 flying-bird flying-bird 5585 6月 18 19:01 VolumeManager.h
-rw-rw-r-- 1 flying-bird flying-bird 2037 6月 18 19:01 Xwarp.cpp
-rw-rw-r-- 1 flying-bird flying-bird 1049 6月 18 19:01 Xwarp.h
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$ ctags -R .
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$ ll tags
-rw-rw-r-- 1 flying-bird flying-bird 48915 6月 22 10:34 tags
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$
3.2 了解tags文件
tags文件的内容包括宏、class、member function、function等所在的文件。示例如下:
tags文件一开始是注释信息,接下来是tags list,每一行的格式:tag name, file name, line number, tag kind. 其中kind含义如下:
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$ ctags --list-kinds=c
c classes
d macro definitions
e enumerators (values inside an enumeration)
f function definitions
g enumeration names
l local variables [off]
m class, struct, and union members
n namespaces
p function prototypes [off]
s structure names
t typedefs
u union names
v variable definitions
x external and forward variable declarations [off]
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$ ctags --list-kinds=c++
c classes
d macro definitions
e enumerators (values inside an enumeration)
f function definitions
g enumeration names
l local variables [off]
m class, struct, and union members
n namespaces
p function prototypes [off]
s structure names
t typedefs
u union names
v variable definitions
x external and forward variable declarations [off]
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$
3.3 打开tag所在的文件
然后用vim -t tagName命令,就可以打开tagName定义所在的文件,并自动定位到tagName所在的那一行。
示例:
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$ vim -t usage
上述命令的执行效果:
要了解这一点,可以查看vim命令的帮助即可:
flying-bird@flying-bird:~/android/android_4.4.2_r2/system/vold$ vim -h
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled May 4 2012 04:10:09)
用法: vim [参数] [文件 ..] 编辑指定的文件
或: vim [参数] - 从标准输入(stdin)读取文本
或: vim [参数] -t tag 编辑 tag 定义处的文件
或: vim [参数] -q [errorfile] 编辑第一个出错处的文件
参数:
-- 在这以后只有文件名
-g 使用图形界面 (同 "gvim")
-f 或 --nofork 前台: 启动图形界面时不 fork
-v Vi 模式 (同 "vi")
-e Ex 模式 (同 "ex")
上面这个功能还是非常强的,因为经常需要查找某个函数的定义,用上面这个命令就非常方便了。
3.4 ts & tp & tn
这3个命令的全称分别是tag list, tag preview, tag next.
前面介绍了可以用vim -t tagName打开一个source file,如果在多个文件中定义了多个名为tagName的language objects,那么这个vim命令也只是打开第一个包括了tagName的这个文件。——包括相同tag名称的文件,是按照文件名进行排序。
此时,可以通过ts来参考当前tagName还存在于哪些文件中。作为例子,我们以整个Android源码创建tags文件。然后执行vim -t usage命令:
flying-bird@flying-bird:~/android/android_4.4.2_r2$ ll tags
-rw-rw-r-- 1 flying-bird flying-bird 1920673761 6月 22 11:00 tags
flying-bird@flying-bird:~/android/android_4.4.2_r2$ vim -t usage
效果如下:
此时执行:ts看usage这个tag一共出现了几次:
这里显示了所有的usage。对于这种有多屏的情况,可以键入空格翻到下一屏。要跳转到目标文件,先Esc,此时屏幕最下面提示输入数字&回车:
比如输入231,然后回车,就自动打开对应的文件:
是不是非常方便?!
注意此时打开的是第231个usage的文件。此时:tn就是打开下一个即232 usage对应的文件,即在当前序号下跳转到下一个文件。对应地,可以练习tp的效果。如果要跳转很远的地方、或直接通过目录&文件名来跳转,还是像前面的操作那样,即输入:ts,列出所有的usage列表,上下翻屏,然后输入数字。
如此,通过:ts, :tp, :tn等就可以快速找到目标tag的位置。
3.5 Ctrl + ]
这个命令也非常有用,其作用是跳转到当前光标所在tag的所在。比如说当前行有一个函数调用,光标在这个函数调用处,通过在命令模式下输入Ctrl+]就可以跳转到该函数定义的地方。
相对应地,如果要再回到上次这个函数调用处呢?就是在命令模式下输入Ctrl+T。
再强调一下,这两个输入不需要先:,而是直接Ctrl+] 和 Ctrl+T。
比如下面这个例子,注意光标的位置(104行):
此时键入Ctrl+]之后,就是下面的效果:
如果再次Ctrl+T就回到上一次的地方。
需要补充的是,上面两个命令的跳转并不局限于当前打开的文件,而可以在vim的多个文件之间,必要情况下,会自动打开新的文件。
3.6 :ta tag
:ta tag是要先输入:的vim命令,它的作用是跳转到tag的定义所在。下面这个示例是以整个Android源码系统创建的tag file来操作,比如在某个文件中输入了:ta VolumeManager,如下:
回车后,就会打开VolumeManager所在的文件:
4. cscope
4.1 安装
直接从ubuntu软件中心,输入cscope,安装cscope.sourceforge.net对应的cscope即可。或者到这个网站上下载代码安装。
检查安装是否成功:
flying-bird@flying-bird:~/android/android_4.4.2_r2$ cscope --version
cscope: version 15.7a
flying-bird@flying-bird:~/android/android_4.4.2_r2$ cscope --help
Usage: cscope [-bcCdehklLqRTuUvV] [-f file] [-F file] [-i file] [-I dir] [-s dir]
[-p number] [-P path] [-[0-8] pattern] [source files]
-b Build the cross-reference only.
-C Ignore letter case when searching.
-c Use only ASCII characters in the cross-ref file (don't compress).
-d Do not update the cross-reference.
-e Suppress the <Ctrl>-e command prompt between files.
-F symfile Read symbol reference lines from symfile.
-f reffile Use reffile as cross-ref file name instead of cscope.out.
-h This help screen.
-I incdir Look in incdir for any #include files.
-i namefile Browse through files listed in namefile, instead of cscope.files
-k Kernel Mode - don't use /usr/include for #include files.
-L Do a single search with line-oriented output.
-l Line-oriented interface.
-num pattern Go to input field num (counting from 0) and find pattern.
-P path Prepend path to relative file names in pre-built cross-ref file.
-p n Display the last n file path components.
-q Build an inverted index for quick symbol searching.
-R Recurse directories for files.
-s dir Look in dir for additional source files.
-T Use only the first eight characters to match against C symbols.
-U Check file time stamps.
-u Unconditionally build the cross-reference file.
-v Be more verbose in line mode.
-V Print the version number.
Please see the manpage for more information.
flying-bird@flying-bird:~/android/android_4.4.2_r2$
4.2 分析源代码文件
首先准备要分析的文件列表,然后用cscope命令进行分析:
find . -name "*.h" > cscope.files
find . -name "*.c" >> cscope.files
find . -name "*.cc" >> cscope.files
find . -name "*.cpp" >> cscope.files
find . -name "*.java" >> cscope.files
cscope -bkq -i cscope.files
最后生成的文件:
flying-bird@flying-bird:~/android/android_4.4.2_r2$ ll cs*
-rw-rw-r-- 1 flying-bird flying-bird 17915097 6月 22 13:44 cscope.files
-rw-rw-r-- 1 flying-bird flying-bird 62021632 6月 22 13:51 cscope.in.out
-rw-rw-r-- 1 flying-bird flying-bird 1082712155 6月 22 13:51 cscope.out
-rw-rw-r-- 1 flying-bird flying-bird 777698136 6月 22 13:51 cscope.po.out
flying-bird@flying-bird:~/android/android_4.4.2_r2$
4.3 配置cscope
从http://cscope.sourceforge.net/cscope_vim_tutorial.html下载csope_maps.vim,并拷贝到/etc/vim/目录下。修改vimrc文件,让它source这个文件:
flying-bird@flying-bird:/etc/vim$ ll
总用量 36
drwxr-xr-x 2 root root 4096 6月 22 14:07 ./
drwxr-xr-x 136 root root 12288 6月 22 08:42 ../
-rw-r--r-- 1 root root 7336 6月 22 13:58 cscope_maps.vim
-rw-r--r-- 1 root root 753 6月 22 14:07 gvimrc
-rw-r--r-- 1 root root 2300 6月 22 14:01 vimrc
-rw-r--r-- 1 root root 662 3月 12 2012 vimrc.tiny
flying-bird@flying-bird:/etc/vim$ sudo vi vimrc
flying-bird@flying-bird:/etc/vim$ cat vimrc
" All system-wide defaults are set in $VIMRUNTIME/debian.vim (usually just
。。。。。。。。。。。。。。。。。。
" Source a global configuration file if available
if filereadable("/etc/vim/vimrc.local")
source /etc/vim/vimrc.local
endif
if filereadable("/etc/vim/cscope_maps.vim")
source /etc/vim/cscope_maps.vim
endif
flying-bird@flying-bird:/etc/vim$
4.4 使用
4.4.1 打开vim
可以使用vim打开一个文件,如:
flying-bird@flying-bird:~/android/android_4.4.2_r2$ gvim -t VolumeManager
此时,和ctags打开第一个定义tag的文件不同的是,现在会首先把所有文件都列出来,供你选择:
4.4.2 Ctrl + \ + S
当光标落在某个tag,此时按下Ctrl + \ + S(快速顺序按下),就会列出这个tag所有出现的地方。示例:
和ctags一样,Ctrl + T会跳会上一次的地方。
4.4.3 多窗口
通过gvim的菜单调出”文件浏览器“窗口;还可以把下面的output窗口拉出来,从而形成多窗口。效果:
5. taglist
5.1 下载&安装
从http://vim-taglist.sourceforge.net/index.html下载,比如taglist_46.zip。
安装方法可以参考http://vim-taglist.sourceforge.net/installation.html。
5.1.1 filetype on
有文档提到要设置filetype on.
在/etc/vim/vimrc中,有这么一段话:
" Uncomment the following to have Vim load indentation rules and plugins
" according to the detected filetype.
"if has("autocmd")
" filetype plugin indent on
"endif
经过验证,没有打开这个注释,下面的各项操作也是可以的。
5.1.2 system
在vim或者gvim环境中,输入“:echo exists('*system')”,其结果要求为1.
5.1.3 解压缩taglist
flying-bird@flying-bird:/etc/vim$ ll
总用量 36
drwxr-xr-x 2 root root 4096 6月 22 14:08 ./
drwxr-xr-x 136 root root 12288 6月 22 17:44 ../
-rw-r--r-- 1 root root 7336 6月 22 13:58 cscope_maps.vim
-rw-r--r-- 1 root root 753 6月 22 14:07 gvimrc
-rw-r--r-- 1 root root 2300 6月 22 14:01 vimrc
-rw-r--r-- 1 root root 662 3月 12 2012 vimrc.tiny
flying-bird@flying-bird:/etc/vim$ sudo cp ~/taglist_46.zip .
[sudo] password for flying-bird:
flying-bird@flying-bird:/etc/vim$ ll
总用量 88
drwxr-xr-x 2 root root 4096 6月 22 19:08 ./
drwxr-xr-x 136 root root 12288 6月 22 17:44 ../
-rw-r--r-- 1 root root 7336 6月 22 13:58 cscope_maps.vim
-rw-r--r-- 1 root root 753 6月 22 14:07 gvimrc
-rw-r--r-- 1 root root 51455 6月 22 19:08 taglist_46.zip
-rw-r--r-- 1 root root 2300 6月 22 14:01 vimrc
-rw-r--r-- 1 root root 662 3月 12 2012 vimrc.tiny
flying-bird@flying-bird:/etc/vim$ sudo unzip taglist_46.zip -d .
Archive: taglist_46.zip
inflating: ./plugin/taglist.vim
inflating: ./doc/taglist.txt
flying-bird@flying-bird:/etc/vim$
5.1.4 helptags
cd到doc目录,以root用户启动vim,然后输入:helptags .命令:
flying-bird@flying-bird:/etc/vim$ cd doc/
flying-bird@flying-bird:/etc/vim/doc$ ll
总用量 80
drwxr-xr-x 2 root root 4096 6月 22 19:08 ./
drwxr-xr-x 4 root root 4096 6月 22 19:08 ../
-rwxr-xr-x 1 root root 69979 2月 26 2013 taglist.txt*
flying-bird@flying-bird:/etc/vim/doc$ sudo vim
flying-bird@flying-bird:/etc/vim/doc$
执行之后会在docs目录下面生成一个tags文件。
5.2 效果
以上配置完成之后,重启vim或gvim。输入:TlistToggle命令即可打开左边的符号窗口,或者输入:help taglist调出taglist的帮助窗口。