介绍一下gnu global,比cscope更方便更快速的索引工具

Vim、Emacs配置和使用
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45
送出感谢: 1 次
接收感谢: 1 次

介绍一下gnu global,比cscope更方便更快速的索引工具

#1

帖子 kevinlei » 2011-08-29 16:30

貌似vim众很少用gnu global啊,都只见着emacs众在用,我觉得有必要在vim众中推广一下。

gnu global是一个类似cscope的工具,也能提供源文件之间的交叉索引。

其独到之处在于,当你生成索引文件以后,再修改整个项目里的一个文件,然后增量索引的过程非常快。

安装过程就不说了,根据各自发行版不同,自个儿装吧。

安装好以后,有global、gtags、gtags-cscope三个命令。global是查询,gtags是生成索引文件,gtags-cscope是与cscope一样的界面。

example:

代码: 全选

$ cd project/
$ gtags

这样就生成了整个目录的索引文件,包括GTAGS、GRTAGS、GPATH三个文件。

你也可以先用find命令生成一个文件列表,叫gtags.files,然后再执行gtags,就会只索引gtags.files里的文件。

example:

代码: 全选

$ cd project/
$ find . -name "*.[ch]" > gtags.files
$ gtags

查询使用的命令是global和gtags-cscope。前者是命令行界面,后者是与cscope兼容的ncurses界面。这里就不多介绍了,重点是如何在vim里查询:

首先进入vim,然后:

example

代码: 全选

:set cscopeprg=gtags-cscope
:cs add GTAGS

然后就可以像cscope一样,用cs find g等命令进行查询了。

当我们更改了某个文件以后,比如project/subdir1/subdir2/file1.c,想更新索引文件(索引文件是project/GTAGS),只消这样:

example:

代码: 全选

$ cd project/subdir1/subdir2/
$ vim file1.c
$ global -u

global -u这个命令会自动向上找到project/GTAGS,并更新其内容。而gtags相对于cscope的优势就在这里:增量更新单个文件的速度极快,几乎是瞬间完成。有了这个优势,我们就可以增加一个autocmd,每次:w的时候自动更新索引文件。

我的设置如下:

代码: 全选

" settings of cscope.
" I use GNU global instead cscope because global is faster.
set cscopetag
set cscopeprg=gtags-cscope
set cscopequickfix=c-,d-,e-,f-,g0,i-,s-,t-
nmap <silent> <leader>j <ESC>:cstag <c-r><c-w><CR>
nmap <silent> <leader>g <ESC>:lcs f c <c-r><c-w><cr>:lw<cr>
nmap <silent> <leader>s <ESC>:lcs f s <c-r><c-w><cr>:lw<cr>
command! -nargs=+ -complete=dir FindFiles :call FindFiles(<f-args>)
au VimEnter * call VimEnterCallback()
au BufAdd *.[ch] call FindGtags(expand('<afile>'))
au BufWritePost *.[ch] call UpdateGtags(expand('<afile>'))
  
function! FindFiles(pat, ...)
     let path = ''
     for str in a:000
         let path .= str . ','
     endfor
  
     if path == ''
         let path = &path
     endif
  
     echo 'finding...'
     redraw
     call append(line('$'), split(globpath(path, a:pat), '\n'))
     echo 'finding...done!'
     redraw
endfunc
  
function! VimEnterCallback()
     for f in argv()
         if fnamemodify(f, ':e') != 'c' && fnamemodify(f, ':e') != 'h'
             continue
         endif
  
         call FindGtags(f)
     endfor
endfunc
  
function! FindGtags(f)
     let dir = fnamemodify(a:f, ':p:h')
     while 1
         let tmp = dir . '/GTAGS'
         if filereadable(tmp)
             exe 'cs add ' . tmp . ' ' . dir
             break
         elseif dir == '/'
             break
         endif
  
         let dir = fnamemodify(dir, ":h")
     endwhile
endfunc
  
function! UpdateGtags(f)
     let dir = fnamemodify(a:f, ':p:h')
     exe 'silent !cd ' . dir . ' && global -u &> /dev/null &'
endfunction

解释几句:

1. 我增加了一个命令叫FindFiles,是用来生成gtags.files文件的,用法如下:

代码: 全选

:FindFiles {pattern} subdir1 subdir2 ...

然后找到的文件就会都添加到当前buffer的最后。

比如,我们用git刚下下来一整套kernel的源码,放在linux-2.6目录下,然后我想生成列表文件,就可以这样:

代码: 全选

:e gtags.files
:FindFiles **/*.[ch] arch/x86 arch/arm block crypto ...
:w

只增加自己想要的目录,而不要的就不增加。

2. 我添加了三条autocmd,其中:

代码: 全选

au VimEnter * call VimEnterCallback()
au BufAdd *.[ch] call FindGtags(expand('<afile>'))

这两条命令会在你打开一个c文件的时候,自动向上查找GTAGS文件,找到以后就会执行:cs add命令添加这个GTAGS文件。

代码: 全选

au BufWritePost *.[ch] call UpdateGtags(expand('<afile>'))

这条命令会在你修改一个c文件并:w以后,自动进入c文件所在目录并执行"global -u"更新索引文件。

最后,还有一个问题,cscope有一个-f参数,这个参数可以指定cscope.out文件的路径。而gtags-cscope的哲学不一样,它是自己一路向上寻找GTAGS文件,所以没有-f参数。而vim调用:cs add的时候,是会使用-f参数的。这样,当:cs add GTAGS文件的时候,就不能指定当前目录的子目录以外的路径。这也导致:cs add命令只能使用一个GTAGS文件。

针对这个问题,我写了一个vim的patch viewtopic.php?f=68&t=342099,在fork出gtags-cscope子进程以后会把子进程chdir()到GTAGS文件所在的目录,这样就OK了。
头像
fanhe
帖子: 2357
注册时间: 2007-03-24 23:45
送出感谢: 0
接收感谢: 9 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#2

帖子 fanhe » 2011-08-29 17:56

据我所知, cscope 也是可以增量更新的

我只想知道 global 对 C++ 的支持, 如果还是跟 cscope 一样搓的话, 真没意思了
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45
送出感谢: 1 次
接收感谢: 1 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#3

帖子 kevinlei » 2011-08-30 9:52

fanhe 写了:据我所知, cscope 也是可以增量更新的

我只想知道 global 对 C++ 的支持, 如果还是跟 cscope 一样搓的话, 真没意思了
确实可以,但是速度非常慢。

拿kernel源码来说的话,在生成索引以后,再修改一个文件,然后分别执行global -u和cscope -bkq,前者是2秒以下,后者抽颗烟回来也完不了。

我基本上不写C++程序,所以不太晓得global的C++到底是啥效果。。。
deepwhite
帖子: 14
注册时间: 2008-01-15 14:11
送出感谢: 0
接收感谢: 0

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#4

帖子 deepwhite » 2011-09-01 9:30

kevinlei 写了:
fanhe 写了:据我所知, cscope 也是可以增量更新的

我只想知道 global 对 C++ 的支持, 如果还是跟 cscope 一样搓的话, 真没意思了
确实可以,但是速度非常慢。

拿kernel源码来说的话,在生成索引以后,再修改一个文件,然后分别执行global -u和cscope -bkq,前者是2秒以下,后者抽颗烟回来也完不了。

我基本上不写C++程序,所以不太晓得global的C++到底是啥效果。。。
global 对 C++ 的支持也就那么回事吧,很久没用 cscope , 忘了 cscope 什么效果了。 global 能很好的搜索函数的定义或者引
用之类、而且支持正则表达式。这一点对 C/C++ 来说都是一样的,但对 C++ 来讲, global 似乎不算智能,如果两个 class 中包含同
样的 member function , gtags 并不知道该跳转到哪一个,只能把两个都列出来。此外, GNU Global 默认不支持 python , 但 cscope
支持。

写 python 和 C++ 时候,我一般用 CEDET 。
头像
Fermat618
帖子: 728
注册时间: 2008-12-28 16:01
送出感谢: 2 次
接收感谢: 15 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#5

帖子 Fermat618 » 2011-09-01 10:01

fanhe 写了:据我所知, cscope 也是可以增量更新的

我只想知道 global 对 C++ 的支持, 如果还是跟 cscope 一样搓的话, 真没意思了
那个要重写整个数据库文件吧。
爱因斯坦会弹钢琴
爱因斯坦会拉小提琴
爱因斯坦会骑自行车
jj112358
帖子: 2
注册时间: 2011-09-02 14:32
送出感谢: 0
接收感谢: 0

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#6

帖子 jj112358 » 2011-09-02 14:34

楼主强大,请教补丁怎么打,我好像没有收到if_cscope.c这个文件~跳转的时候老说有错,烦啊
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45
送出感谢: 1 次
接收感谢: 1 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#7

帖子 kevinlei » 2011-09-02 15:40

jj112358 写了:楼主强大,请教补丁怎么打,我好像没有收到if_cscope.c这个文件~跳转的时候老说有错,烦啊
进入vim源码目录以后,执行:

代码: 全选

patch -p1 < ../gtags-cscope.diff
jj112358
帖子: 2
注册时间: 2011-09-02 14:32
送出感谢: 0
接收感谢: 0

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#8

帖子 jj112358 » 2011-09-02 15:56

我悲剧~我是yum装的,怎么办。楼主赐教

global的确好用啊,比cscope快多了。而且我在cscope下硬是没有找到好的自动更新的方法。
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45
送出感谢: 1 次
接收感谢: 1 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#9

帖子 kevinlei » 2011-09-02 17:03

。。。从源码编一个吧。编之前先打patch
头像
widon1104
帖子: 829
注册时间: 2008-07-17 10:55
送出感谢: 0
接收感谢: 2 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#10

帖子 widon1104 » 2012-01-07 21:53

我给内核加上一个回车,更新cscope数据库需要1分钟以上,所以试着使用global
但是发现global fake cscope有问题
我先生成global数据库
gtags
然后打开vim
:set cscopeprg=gtags-cscope
:cs add GTAGS
然后
:grep main .
跳到第一个文件,cs f s 第一个宏定义
:cs f s MD5_DIGEST_SIZE
出现E262: error reading cscope connection 0

我把:cs add GTAGS
改成:cs add $PROJECT_HOME/GTAGS $PROJECT_HOME
依旧不行
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45
送出感谢: 1 次
接收感谢: 1 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#11

帖子 kevinlei » 2012-01-11 22:35

把global更新到最新版(我是6.0),然后给vim打上这个补丁试试:
viewtopic.php?f=68&t=342099
头像
widon1104
帖子: 829
注册时间: 2008-07-17 10:55
送出感谢: 0
接收感谢: 2 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#12

帖子 widon1104 » 2012-01-11 23:17

kevinlei 写了:把global更新到最新版(我是6.0),然后给vim打上这个补丁试试:
viewtopic.php?f=68&t=342099
同样的问题,楼主那里正常的?我把set autochdir注销了,global更新了,补丁打了,依旧不行阿,楼主试过行吗?
主要就是2问题,使用global不能切换目录,不能set grepprg=grep\ -nri\ --include=*.{c,h}使用:grep.....
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45
送出感谢: 1 次
接收感谢: 1 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#13

帖子 kevinlei » 2012-01-13 0:33

我就是因为global不能切目录,不能:cs add多个GTAGS文件,才动手写的这个补丁啊,是针对hg clone出来的最新版vim的。

我打了补丁以后就没问题了。

你是不是补丁打得不对?打补丁的时候有错误提示吗?

另外,gtags跟grepprg没有关系的啊,grepprg的问题应该是你别的设置不对吧。
头像
widon1104
帖子: 829
注册时间: 2008-07-17 10:55
送出感谢: 0
接收感谢: 2 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#14

帖子 widon1104 » 2012-01-13 22:42

我知道E262: error reading cscope connection 0 这个问题怎么产生的了
我在内核代码里面 ;grep main .
因为结果很多,我用Ctrl-C中断
以后在使用cs f *
就会出现这个错误(使用cs reset可以恢复)
如果我等到grep搜索完毕,就不会出现这个错误

使用cscope会出现同样的问题

vim打补丁,可能是我打完补丁编译vim,./configure的时候没有加上 --enable-cscope出问题了吧。。。。
这些用户感谢了作者 widon1104 于这个帖子:
kevinlei (2012-01-14 13:08)
评价: 3.7%
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45
送出感谢: 1 次
接收感谢: 1 次

Re: 介绍一下gnu global,比cscope更方便更快速的索引工具

#15

帖子 kevinlei » 2012-01-14 13:02

还真是,我这儿照你这么操作也会有这个错误,不管cscope还是global都一样。grep怎么跟cscope搞到一起去了。。。

我这儿是确实加了--enable-cscope的。
回复

回到 “Vim和Emacs”