CSCOPE使用中问题小解
拥有了某种工具,往往不等于就能使用好这种工具。拥有工具简单,用好工具、发挥出最大作用则较难。CSCOPE让VIM的使用者有了与SourceInsight"平起平坐“的机会,但是能否将CSCOPE的功能发挥出来还要看你是如何使用它了。
自从VIM”重装上阵“以后,我一直在使用CSCOPE。在使用过程中还是发现了一些”别扭“的事情。一般我会在一个大型Project的源代码的顶层目录使用CSCOPE -Rbq来生成cscope.out文件,如果你在cscope.out所在目录执行VIM的话,VIM会优先将cscope.out作为”符号交叉索引库“(与ctags相比),但是如果你在某个子目录下执行VIM进入编辑状态的话,因当前目录没有cscope.out,所以VIM无法加载cscope.out文件,也就无法在文件间跳转。而必要时你还需要手动执行命令行:cs add {TOP_LEVEL_PATH}/cscope.out才能连接到cscope,发挥其功用。
还有一种情况,如果你有两份基本相同的代码库,其中一份A建立了cscope.out文件(在A的顶层目录使用CSCOPE -Rbq),而另一份B没有建立,当使用B查看代码或编写代码时,手动add A库的cscope.out文件,然后打开B库子目录的一个文件,找到一个符号,用ctrl+]进行跳转,VIM会列出符号列表,当你选择一个时,VIM却提示你“E429: File xx/yy.h does not exist”,原因很简单,就是Cscope以相对路径存储了符号的位置,你从B库的工作目录下当然跳不过去了。
现在我们就要解决这两个问题,我们要做到:
1) 无论在任何目录下执行VIM,VIM都会自动加载当前阶段常用的cscope.out,而无需手动加载;
2) 让cscope.out内的符号以绝对路径的形式存储,这样无论在何处进入VIM,都能跳转到相应的符号定义的文件中;
其实解决上述两个问题的方法有多种,这里只是先说说我的一种方法,估摸着还不是最优的。在cscope官方有篇文章“Using Cscope on large projects”,里面关于cscope.out生成的方法可以解决第二个问题,即使用cscope.files来生成cscope.out。cscope.files中的内容很简单,就是文件列表,将你要进行扫描的所有文件的路径cscope.files中,然后执行cscope -bqk即可得到cscope.out。如果你要解决问题2,那你就将要进行扫描的文件的绝对路径名加入到csccope.files中。用find命令可以轻松帮你做到这一点。这里将这个工作放到了一个shell脚本中去完成了,脚本具有一定的通用性(我的脚本水平:菜鸟级^_^):
/* gen_cscope_files.sh */
#! /bin/bash
TARGET='/export/home1/username/cscope_db/cscope.files'
gen_cscope_files_usage() {
echo "gen_cscope_files.sh 源码顶层目录(绝对路径) 待扫描子目录1 [待扫描子目录2] … [待扫描子目录N]"
}
if [ -z ${1} ]; then
echo "请输入起始目录!"
gen_cscope_files_usage
exit 1
fi
if [ ${1:0:1} != '/' ]; then
echo "请输入起始目录的绝对路径形式!"
gen_cscope_files_usage
exit 1
fi
if [ ${#} -lt 2 ]; then
echo "请输入你要扫描的子目录列表!"
gen_cscope_files_usage
exit 1
fi
if [ -s ${TARGET} ]; then
cat /dev/null > ${TARGET}
fi
for dir in $@
do
if [ ${dir} != ${1} ]; then
find ${1}/${dir} \
-name "*.[hc]" \
-print >> ${TARGET}
fi
done
这样你只要选择好你的cscope.files的存放位置(在上面的脚本中是写死的,当然你也可以修改脚本,通过命令行参数传入cscope.files的存放位置),给gen_cscope_files.sh一个源码的顶层目录(绝对路径),再给出你要扫描的子目录列表即可,比如:gen_cscope_files.sh /export/home/username/proj/foo include src
以上解决了问题2,那问题1呢?我们在.vimrc中做文章。以下代码保证了每次vim被执行后都会将上面生成的cscope.out加载。
if has("cscope")
if filereadable("/export/home1/username/cscope_db/cscope.out")
cscope add /export/home1/username/cscope_db/cscope.out
endif
endif
到目前为止,你在B库中在任意目录下打开的文件都可以找到相应符号的位置。
评论