文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>GNU Global Source Code Tag System

GNU Global Source Code Tag System

时间:2010-04-24  来源:buxoman

GNU Global是一个源码阅读的好工具。能独立使用,而且与Emacs结合的很好。准备花点儿时间学习一下。而且要阅读和学习操作系统代码,没有一个像Souce Insight一样好用的代码阅读工具,难度真的不小。

下面就把学习时的一些要点记录下来。

1. 工程的概念。

Global把一个目录及其子目录当作一个工程。

2. 准备工作

最首要的工作是,在源代码的根目录下执行gtags程序。

手册举了一个FreeBSD的例子:
$cd/usr/src/usr.bin/vi
$gtags

结果:gtags将把这个vi目录及其所有子目录下的文件当作一个Project(工程),在这个根目录下生成四个数据库文件,分别是:GPATH, GRTAGS, GSYMS, GTAGS。呵呵,都是G开头的。
手册对这四个文件的作用有个说明,分别是:
GPATH  路径名称数据库;
GRTAGS  引用数据库;
GTAGS   定义数据库;
GSYMS   符号数据库,存放没有出现在GTAGS中的符号;

这些数据库可是要些存储空间的。手册用FreeBSD7内核做例子,给出了数据库存储空间:
source code (/usr/src/sys)    123 MB

GPATH                           1 MB
GTAGS                          26 MB
GRTAGS                         22 MB
GSYMS                          23 MB
-------------------------------------
total of tag files             72MB

(呵呵,我正打算看看FB8的sys目录呢,这个例子正好给我提供现实参考)

好,到了这里,先实地操作一把,尝尝鲜!

3. 在Windows XP上安装global

我在Windows XP上看代码。所以先从http://www.gnu.org/software/global/下给出的一个链接,下载到了Windows版本的global和htags。把htags替换global原本自己的,据说是修正了一个BUG。我也不知道,反正替换了就得了。

到Freebsd的sys目录下试一把:
D:\FreeBSD\release8\sys>gtags
(要等几分钟)
D:\FreeBSD\release8\sys>dir
2010-04-24  22:04         1,425,408 GPATH
2010-04-24  22:05        32,710,656 GRTAGS
2010-04-24  22:05        27,394,048 GSYMS
2010-04-24  22:04        29,122,560 GTAGS

呵呵,不错。做饭的米准备好了。接着就等烧火的EMACS咯。

先看看我的global安装目录的内容吧:

C:\Application>tree /F glo581wb
结果显示:
C:\APPLICATION\GLO581WB
├─bin
│      global.exe
│      gozilla.exe
│      gtags-cscope.exe
│      gtags-parser.exe
│      gtags.exe
│      htags-old.exe
│      htags.exe

├─manifest
│      glo581wb.mft
│      glo581wb.ver

└─share
    ├─gtags
    │  │  AUTHORS
    │  │  bless.sh.tmpl
    │  │  BOKIN_MODEL
    │  │  BOKIN_MODEL_FAQ
    │  │  ChangeLog
    │  │  COPYING
    │  │  DONORS
    │  │  FAQ
    │  │  ghtml.cgi.tmpl
    │  │  global.cgi.tmpl
    │  │  globash.rc
    │  │  gtags-cscope.vim
    │  │  gtags.conf
    │  │  gtags.el
    │  │  gtags.pl
    │  │  gtags.vim
    │  │  INSTALL
    │  │  LICENSE
    │  │  NEWS
    │  │  README
    │  │  README.win32
    │  │  style.css
    │  │  THANKS
    │  │
    │  └─icons
    │          back.png
    │          bottom.png
    │          c.png
    │          dir.png
    │          first.png
    │          help.png
    │          index.png
    │          last.png
    │          left.png
    │          n_bottom.png
    │          n_first.png
    │          n_last.png
    │          n_left.png
    │          n_right.png
    │          n_top.png
    │          pglobe.png
    │          right.png
    │          text.png
    │          top.png
    │
    ├─info
    │      global.info
    │
    └─man
        └─cat1
                global.1
                gozilla.1
                gtags-cscope.1
                gtags-parser.1
                gtags.1
                htags.1

4. 在Emacs中配置global

先把global安装目录下的gtags.el拷贝到emacs安装目录下的lisp目录。

在Emacs中有两种办法启动gtags。
(1) 手动 M-x gtags-mode RET
(2) 启动C模式时自动启动 
(require 'gtags)
(setq c-mode-hook
      '(lambda ()
       (gtags-mode 1)))

这种启动的gtags模式,是minor模式,不是major模式,不过正好与C模式配套使用。

先试一试看看是否可用了。打开一个C文件,在一个结构体类型名上执行M-x gtags-find-tag RET <name> RET。在提示输如名称时,能自动选择光标所在的名称。最后回车后直接跳到了结构的定义处。真不错!

【注:M-. 这个按键绑定到函数gtags-find-tag】

好了,现在应该开始利用Emacs+global傲游于代码的汪洋大海中了!

5. 查找数据类型的定义

我试着在uint8_t这个类型上执行查找,结果Emacs专门用一个窗口显示出了多处定义:

uint8_t   52 boot/efi/include/i386/efibind.h typedef unsigned char       uint8_t;
uint8_t   65 boot/efi/include/i386/efibind.h typedef unsigned char       uint8_t;
uint8_t   77 boot/efi/include/i386/efibind.h typedef unsigned char       uint8_t;
uint8_t   52 boot/efi/include/ia64/efibind.h typedef unsigned __int8     uint8_t;
uint8_t   65 boot/efi/include/ia64/efibind.h typedef unsigned char       uint8_t;
uint8_t   77 boot/efi/include/ia64/efibind.h typedef unsigned char       uint8_t;
uint8_t   42 dev/mxge/mxge_mcp.h typedef unsigned char       uint8_t;
uint8_t   36 geom/virstor/binstream.h #define uint8_t unsigned char
uint8_t   50 netinet/in.h     typedef    __uint8_t        uint8_t;
uint8_t   58 sys/stdint.h     typedef    __uint8_t        uint8_t;
uint8_t   84 sys/types.h      typedef    __uint8_t    uint8_t;

把光标移动到你想去的定义处,按回车就跳转到了那个文件中这个类型的定义。

【这个专门窗口的模式叫做GTAGS SELECT MODE(gtags 选择模式)】

或许你还想看看上面多处定义中的其它处定义,怎么回到这个列表去呢?执行M-x gtags-pop-stack就可以了。

【按键M-*绑定到函数gtags-pop-stack】

看完了某结构的定义,大部分情况下是立即返回到原来的代码处继续阅读。怎么做呢?其实很简单,跟上面一样,仍然gtags-pop-stack就可以了。(似乎gtags在每一次跳转前都把当前位置坐了bookmark放到一个栈结构中了)。可以连续执行这个动作,直到你第一次进行查找的地方。跟source insight的功能一样。

在显示符号定义位置的时候,文件名和路径都显示出来了,这个路径是相对于源代码根目录的路径。是可以修改的,相关变量是gtags-path-style, 可以取三种值root(默认值,相对于源码根目录), relative(相对于当前目录), absolute(绝对路径)。

【对变量的修改,可以用M-x customize-variable命令; 比较unix风格一点的,是在.emacs文件里配置:
(setqgtags-mode-hook
’(lambda()
(setqgtags-path-style’relative)))


6. 查找一个函数被引用的地方

有时候要看一个函数被哪些函数调用了,在Emacs中执行M-x gtags-find-rtags。

比如查看函数nd6_llinfo_settimer的引用,得到很多结果,在gtags选择模式窗口中显示:
nd6_llinfo_settimer  495 netinet6/nd6.c               nd6_llinfo_settimer(ln, INT_MAX);
nd6_llinfo_settimer  498 netinet6/nd6.c               nd6_llinfo_settimer(ln, ln->ln_ntick);
nd6_llinfo_settimer  518 netinet6/nd6.c               nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_llinfo_settimer  544 netinet6/nd6.c               nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
nd6_llinfo_settimer  561 netinet6/nd6.c               nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_llinfo_settimer  565 netinet6/nd6.c               nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
nd6_llinfo_settimer  571 netinet6/nd6.c               nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_llinfo_settimer 1022 netinet6/nd6.c       nd6_llinfo_settimer(ln, -1);
nd6_llinfo_settimer 1044 netinet6/nd6.c                   nd6_llinfo_settimer(ln,
nd6_llinfo_settimer 1047 netinet6/nd6.c                   nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
nd6_llinfo_settimer 1147 netinet6/nd6.c           nd6_llinfo_settimer(ln,
nd6_llinfo_settimer 1861 netinet6/nd6.c           nd6_llinfo_settimer(ln,
nd6_llinfo_settimer  401 netinet6/nd6.h   void nd6_llinfo_settimer __P((struct llentry *, long));

7. 若用gtags-find-tag没有找到某个符号的定义,那么就试一试gtags-find-symbol

8. 查找字符串,可以试一试 gtags-find-with-grep.

9. 还支持正则表达式呢:  Find Symbol: ^put_  <== 查找以put_开头的符号

10. 也支持自动补全,就是在提示你输出待查找的符号名称时可以使用。【要是能在编辑的时候使用那该多爽啊!完全可以抛弃source insight了!】

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载