29

xyf问:

请教大哥一个ctags或cscope使用的问题,我的开发工程很大,有上百万行代码,

之前使用sourceinsight,每次编辑代码,会自动更新函数、变量等符号信息,使用vim替换sourceinsight后,每次修改源代码后,如果不手动更新一下tag和cscope.out,相关的跳转就会不正确了,但是更新的话又要很久,请问有没有增量更新tag或cscope.out,或者你是如何解决这个棘手的问题的?谢谢!

这个问题我在写vim使用进阶: 使用标签(tag)文件时也想过,当时在网上查找了很多资料,不过并没有找到一个好的解决方法。后来在开发的过程中,实时更新tag文件和cscope数据库的需求并不强烈,也就放下了。

刚好xyf问这个问题,我把当时我的一些想法写出来,供大家参考。这些都只是初步的想法,没有经过实际的验证。有兴趣的朋友可以试一下,把试验结果反馈给我。

我以Linux系统为例,在windows上应该也能够实现(借助cygwin,以及windows的计划任务)。

其实source insight自动更新函数、变量等信息都是在后台自动进行的,那么我们也可以考虑在后台自动更新tag文件和cscope数据库。

在Linux下,我们可以利用cron守护进程来完成后台自动更新的操作。思路是,让cron进程每隔15分钟(或者更短)扫描一下tag文件和cscope数据创建后发生改变的项目文件,然后为这些项目文件单独生成一个tag文件和cscope数据库。我们知道,在vi里我们可以同时添加多个tag文件和cscope数据库,我们只要把发生改变文件的tags和cscope数据库加到vim里,应该就可以查找、跳转新增的函数了。不过这样做有一个缺点:就是那些修改过的文件,会在vim的tag文件和cscope数据库中出现两次(在原有tag文件中以及新生成的tag文件中),也许会造成使用的不便。

另外,还可以在稍长的时间里(比如一小时)由cron自动为项目中全部文件生成一次tag文件和cscope数据库,并把修改文件的tags和cscope数据库清空。如果担心为全部项目生成tag文件太耗系统资源的话,可以使用Linux中的at守护进程来生成全部文件的tag和cscops数据库,at服务只在系统空闲时才会运行。

下面给一个demo脚本,来自动查找项目中最近改变的文件,并为其生成tag文件和cscope数据库(未经过测试):

#! /bin/sh

# This demo script will find the modified files in your project,
# and generate a ctags file and cscope database for these files.
# This script is NOT tested yet!
# by Easwy Yang, 2009/03/29

# vars
PRJ_DIR=/home/easwy/prjtest
PRJ_TAG_FILE=${PRJ_DIR}/tags
PRJ_MOD_TAG_FILE=${PRJ_DIR}/newtags
PRJ_MOD_CSCOPE_FILE=${PRJ_DIR}/newcscope.out
MOD_FILES=${PRJ_DIR}/mod_files

FIND=/usr/bin/find
CTAGS=/usr/bin/ctags
CSCOPE=/usr/bin/cscope

# find modified files
# you can modify this command to exclude the object files, etc.
${FIND} ${PRJ_DIR} -type f -newer ${PRJ_TAG_FILE} > ${MOD_FILES}

# generate tag file
${CTAGS} -f${PRJ_MOD_TAG_FILE} -L${MOD_FILES}
${CSCOPE} -bq -f${PRJ_MOD_CSCOPE_FILE} -i${MOD_FILES} 

在这个脚本里,/home/easwy/prjtest是项目所在的目录,tags文件则是参考文件,在项目目录中修改日期比tags文件更新的文件都会被find命令查找出来,并且为之生成tag文件和cscope数据库。

希望对大家有所帮助,更希望这一块砖头,能引出更好的玉。

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/automatically_update_ctags_tag_cscope_database/

文章的脚注信息由WordPress的wp-posturl插件自动生成

文本处理

21条评论 添加评论

  1. alickguo
    2009/04/04 17:29 | #1

    请教一个Cygwin下vim+cscope的问题.
    cscope connecte后过了大概两三小时,再使用cs find 查找时会出现查找失败,vim关闭重开后重新connecte后又恢复了,找了n久没有找到解决方法,错误信息如下:
    E262: error reading cscope connection 0
    E259: no matches found for cscope query f of ddm_frame.c
    vim与cscope的版本信息如下:
    $ vim –version
    VIM – Vi IMproved 7.2 (2008 Aug 9, compiled Feb 23 2009 13:47:33)
    Compiled by alickguo@0kigv8dr4ef5

    $ cscope –version
    cscope: version 15.6

  2. 2009/04/04 21:04 | #2

    @alickguo
    我似乎也遇到过这样的问题,我记不清是什么原因导致的,好像是因为在vim中切换目录?
    遇到这种情况,不必关闭vim,先使用”:cs kill 0″断开和cscope的连接,然后再”:cs add cscope.out”重新连就可以了。
    如果总出现这种情况又找不到原因的话,把上面两个命令map成一个快捷键,会使你的困扰小一点。

  3. 2009/04/10 15:33 | #3

    @Easwy
    关于自动更新tag的一点儿想法:
    1.cscope是支持增量更新的,cscope.files不变的话,默认参数就是增量。
    2.而ctags是不支持增量更新的。但对于支持多tags的编辑器(如VIM),可以考虑分层次的生成多tags,然后根据修改的文件更新(重建)相应的tags即可。可以参考http://ctags.sourceforge.net/faq.html#15
    3.最后将文件保存指令和更新tags MAP成一个快捷键。

    其实个人对自动更新tags的需求也不是很强,对于一个session,有taglist就行了。做完本地和代码库的同步后,总是会重新建立数据库的,用server也没有觉得慢,而且这点时间可以休息休息眼睛^_^

  4. 2009/04/11 10:40 | #4

    @oldbee
    是的。
    如果再加上cron定时更新tag和cscope的话,应该可以满足大多数人的需求。cron的更新间隔可以根据自己的需要调整。

  5. karl
    2009/04/11 22:47 | #5

    好!
    除了这一个问题,还有一个不同工程间tag的切换的问题,vi好像有个tag switch的插件,不过偶还没去看怎么用。。。现在用vi只是用来查找,看代码的关联关系还是在si中方便。。。

  6. 2009/04/11 23:46 | #6

    @karl
    什么叫不同工程间tag切换?
    如果是两个不相关的工程,开两个vim看不就行了
    如果是同一个工程,只生成一个大tag文件就可以了

  7. karl
    2009/04/12 10:53 | #7

    两个不同的工程。。。tag文件如果所有的工程做成一个的话,查找的时候会重复,不准之类的。。。如何在vimrc里针对一个工程的目录配置一个tag文件?

  8. 2009/04/12 12:05 | #8

    @karl
    你是不是想在工程A的目录中时,使用工程A的tag文件,切换到工程B的目录时,使用工程B的tag文件?
    你可以试一下vim的project插件

  9. karl
    2009/04/12 22:37 | #9

    是的:)
    而且还有一个问题就是:vi要在做tag所在目录为相对目径的情况下,打开源文件,才能用cscope搜定义什么的。。。但我一般都会先切换到下面的子目录去。。。然后再vi xxx.cpp,这样子就会导致没法搜索。不知这个问题有没有解决的办法?

  10. 2009/04/12 23:42 | #10

    @karl
    生成一个绝对路径的tag文件,以及绝对路径的cscope文件,就可以解决你的问题。不过你也许需要在vimrc里设置一下,发现当前目录是项目A的子目录时,使用项目A的tag,否则就用项目B的。

    不过我通常都是在项目的根目录下生成整个项目的tag文件/cscope文件,因为使用了lookupfile插件,直接在vim中打开文件已经很方便了,不需要cd到某个目录再打开文件。
    在开发过程中我基本上根本不退出vim,在vim里就可以搞定一切,实在不行,就再开一个putty/rxvt终端来做vim里不好做的工作。

  11. 2009/04/13 12:36 | #11

    Easwy :
    @karl
    不过我通常都是在项目的根目录下生成整个项目的tag文件/cscope文件,因为使用了lookupfile插件,直接在vim中打开文件已经很方便了,不需要cd到某个目录再打开文件。

    @karl
    我和Easwy的做法基本一样,在项目根目录下建立一个workspace.vim,然后在.vimrc里面
    if filereadable(“workspace.vim”)
    source workspace.vim
    endif

    workspace.vim里放置项目相关配置:path/cscope_db/ctags/lookupfile_tags/DoxygenToolkit_comment/errorformat,以及一些特殊的filetype。

  12. karl
    2009/04/13 21:07 | #12

    oldbee :

    Easwy :@karl不过我通常都是在项目的根目录下生成整个项目的tag文件/cscope文件,因为使用了lookupfile插件,直接在vim中打开文件已经很方便了,不需要cd到某个目录再打开文件。

    @karl我和Easwy的做法基本一样,在项目根目录下建立一个workspace.vim,然后在.vimrc里面if filereadable(”workspace.vim”)source workspace.vimendif
    workspace.vim里放置项目相关配置:path/cscope_db/ctags/lookupfile_tags/DoxygenToolkit_comment/errorformat,以及一些特殊的filetype。

    我更倾向于用这种方法:

    生成一个绝对路径的tag文件,以及绝对路径的cscope文件,就可以解决你的问题。不过你也许需要在vimrc里设置一下,发现当前目录是项目A的子目录时,使用项目A的tag,否则就用项目B的。

    还不知脚本怎么写。。。
    我看代码关联一般是在si里面看,查找变量在文件中被修改的地方一般在vi中用*#查找。。。
    现在有两个问题:
    1、windows下的taglist遇到中文路径没法识别
    2、上回装了一个srcexpl.vim插件,用着感觉怎么看着就不如SI的关联窗口,后来发现问题所在,在SI中,代码的关联窗口的字体是比代码窗口的字体小一号,而在srcexpl.vim插件中的字体是和主窗口一样大小的。。。有没有办法把字体变小?

  13. 2009/04/13 22:27 | #13

    @karl
    脚本其实也很简单的,你:help一下就差不多了

    taglist的中文路径问题,好像有人已经解决过了,在网上搜一下吧
    vim中不能设置不同大小的字体。
    不过我觉得,既然已经选择了vim,要学会适应它的风格,毕竟每个程序都不一样的,不能用一个程序的标准去要求其它的程序,这种先入为主太偏颇了

  14. karl
    2009/04/13 23:22 | #14

    @Easwy

    Easwy :@karl脚本其实也很简单的,你:help一下就差不多了
    taglist的中文路径问题,好像有人已经解决过了,在网上搜一下吧vim中不能设置不同大小的字体。不过我觉得,既然已经选择了vim,要学会适应它的风格,毕竟每个程序都不一样的,不能用一个程序的标准去要求其它的程序,这种先入为主太偏颇了

    嗯 好
    我在UBUNTU下,用SSH登陆上RH AS的主机,使用VIM,没法和系统共享剪贴板,用:reg查看,没有看到*和+寄存器,请问是为什么,应该怎样设才能有*和+两个寄存器?--才能使各个SSH窗口之间通过*和+寄存器进行拷贝?

  15. karl
    2009/04/13 23:48 | #15

    Easwy :@karl脚本其实也很简单的,你:help一下就差不多了
    taglist的中文路径问题,好像有人已经解决过了,在网上搜一下吧vim中不能设置不同大小的字体。不过我觉得,既然已经选择了vim,要学会适应它的风格,毕竟每个程序都不一样的,不能用一个程序的标准去要求其它的程序,这种先入为主太偏颇了

    网上只搜到这哥们的办法:
    http://qzone.qq.com/blog/6698756-1218395519
    但试了并不好使
    虽然运行taglist不报错了,但没有显示函数列表出来

  16. 2009/04/14 12:51 | #16

    @karl
    既然是用ssh登陆运行VIM,那么VIM进程是跑在Server上的,寄存器之类的也是存在Server上,自然没有办法通过VIM寄存器在client上共享剪贴板。
    我一般是用terminal的特性,在vim中用shift+鼠标左键拖拽 选定要复制的区域,然后复制(xterm选定后已经自动复制了),到另一个窗口shift+Insert粘贴(vim要在非Normal模式下)。
    另外,*和+寄存器只有在图形模式下(gvim)才有。

  17. 2009/04/14 13:37 | #17

    @oldbee
    呵呵,和我用的方法一样。

    另外,既然本地和远端运行的都是Linux,那么完全可以在RH上起一个gvim,然后把这个gvim显示在你本地Linux上。做法可以参考我的这篇文章使用cygwin X server实现Linux远程桌面 (for windows),虽然是讲cygwin的,不过X serrver的原理都是一样的。

  18. 2009/04/14 13:52 | #18

    @karl
    taglist中文名的问题我没解决过,一般也很少使用中文做目录名。看看taglist的FAQ吧:
    :help taglist-faq

  19. karl
    2009/04/14 22:26 | #19

    Easwy :@karltaglist中文名的问题我没解决过,一般也很少使用中文做目录名。看看taglist的FAQ吧::help taglist-faq

    又试了一下,可以了,之前可能敲错了。

  20. roddger
    2009/08/16 09:34 | #20

    是否可以用autocmd来实现?扑捉对文件的写入事件,当对文件有写入动作之后,重新生成Tag。或者直接用一个快捷键,就像IDE里的编译一样,按下键之后,就重新生成了。

  21. 2009/09/05 14:39 | #21

    我的做法是写个shell更新tags/cscope.out,在vimrc里面绑定快捷键,需要时直接快捷键更新并自动在当前vim里面读取

评论本文