GNU Global Practices

Table of Contents

主要根据GNU Global Tutorial介绍一下其在 Emacs 下面的使用。 GNU Global(全称为 GNU Global source code tagging system,以下简称 Global) 是一个可以跨越各种环境的代码标记系统,支持 Emacs、VI、Bash Shell 甚至是浏览器,主要用来查找代码中各种符号的定义和引用。最新版本的 global(6.5.2)除了软件本身支持的 C, C++, Yacc, Java, PHP4 and assembly 六种语言,在将 Pygments 和 Exuberant Ctags 作为解析器后,还可以支持 Awk, Dos batch, COBOL, C, C++, C#, Erlang, Fortran, Java, JavaScript, Lisp, Lua, Pascal, Perl, PHP, Python, Ruby, Matlab, OCaml, Scheme, Tcl, TeX, Verilog, Vhdl and Vim 等 25 种语言。helm-gtags 是 Emacs 版本的 Global 前端,用其可以方便的在符号的定义和引用间进行跳转。Windows 二进制版本的 Global 中自带了 ctags,所以只需额外安装 Pygments。 安装过程中需要新建 GTAGSCONF 和 GTAGSLABEL 两个环境变量来指示 Global 将 pygments 作为分析器,具体参见 Global 源码包 plugin-factory 目录下两个 HOWTO 文件。需要注意的是 global 只能分析当前工程目录下的文件,不能跟踪解析工程文件中引用到其他地方的文件。不能解析 Cpp .h 头文件需要设置环境变量 GTAGSFORCECPP 环境变量。(待解决)

1 Manual

1.1 Overview of this tool

1.1.1 What is GNU GLOBAL?

GNU GLOBAL is a source code tag system that works the same way across diverse environments, such as Emacs editor, Vi editor, Less viewer, Bash shell, various web browsers, etc. You can locate specified symbols, such as functions, macros, structs and classes in your source files and move there easily. It is useful for hacking large projects which contain many sub-directories, many #ifdef and many main() functions. It is similar to ctags or etags, but is different from them at the point of independence of any editor.

GNU Global(全称 GNU GLOBAL Source Code Tag System)是一个源代码标记系统,以相同的方式工作在不同的环境中,比如 Emacs editor, Vi editor, Less viewer, Bash shell, various web browsers 等等。通过找到的指定的符号,比如函数(function)、宏(macros)、结构体(struct)、类(class),并进行快速跳转。对于 hack 那些包含很多子目录,很多#ifdef 和 main()函数的大型项目是很有用的。它类似 ctags 或者 etags,但在独立于编辑器这一点上是不同的。

1.1.2 Concept of project

GNU GLOBAL can treat a source tree containing sub-directories as a project. Anywhere in the project, you can utilize a high performance tag database. You need not specify where the database is, as global(1) locates it by itself. Because of this feature, you can move freely in a project, and in and out of many projects.

GNU GLOBAL 将包含子目录的源码树看作是一个项目。在项目的任意地方,都可以利用一个高性能的 tag 数据库。不需要指定数据库的位置,global 会自己定位。正式由于这个特性,可以在项目中自由移动,也可以在项目间移动。

1.1.3 Features

GNU GLOBAL has the following features:

  • supports C, C++, Yacc, Java, PHP4 and assembly.
  • works the same way across diverse environments like follows:
    • Shell command line
    • Bash shell
    • Vi editor (Nvi, Elvis, vim)
    • Less viewer
    • Emacs editor (Emacs, Mule, Xemacs)
    • Web browser
    • Doxygen documentation system
  • finds locations of specified symbol quickly.

    快速查找指定符号(symbol)位置。

  • locates not only definitions but also references.

    除了定位定义还可以定位引用。

  • allows duplicate tags.

    允许重复 tag。

  • locates paths which matches to the specified pattern.

    定位匹配指定模式的路径。

  • hierarchical searches by default.

    默认层次搜索。

  • searches not only in a source project but also in library projects.

    不仅在源码工程搜索,还可以在库工程搜索。

  • generates completion list for completing input method.

    为补全输入方法产生补全列表。

  • supports various output formats.

    支持多种输出格式。

  • allows customizing of a set of candidate files to be tagged.

    允许定制一组可以用来标记的候选文件。

  • understands POSIX 1003.2 regular expression.

    了解 POSIX 1003.2 正则表达式。

  • supports idutils as an external search engine.

    支持 idutils 作为外部的搜索引擎。

  • tag files are independent of machine architecture.

    tag 文件独立于机器的体系结构。

  • supports incremental updating of tag files.

    支持标记文件的递增更新。

  • plug-in parser is available to treat new language.

    解析器支持插件用来分析新语言。

  • supports customizing using ‘gtags.conf’.

    通过使用 gtags.confg 来进行定制。

  • generates a hypertext of source code.

    为源码生成超文本文件。

  • compact format to save disk space.

    格式紧凑,节省磁盘空间。

  • supports client/server environment (TRAMP ready).

    支持客户端/服务器环境。

  • ignores binary files, dot files and specified files.

    忽略二进制文件、点文件和指定文件。

  • includes cscope-compatible program (gtags-cscope).

    包括 cscope 兼容程序(gtags-cscope)。

  • includes grep-like command (-g command).

    包括 grep-like 命令(-g command)。

  • supports grep-like symbol highlighting.

    支持 grep-like 符号高亮。

2 Command line

You can use tag facilities from the shell command line. It is a big merit of GLOBAL compared with any other tag system.

可以从命令行使用 tag 机制。和其他 tag 系统相比,这是一个很大的优点。

2.1 Preparation

Before beginning, please read the FAQ (Frequently Asked Questions) file.

开始前,先去阅读 FAQ 文件。

more /usr/local/share/gtags/FAQ

First of all, you must execute gtags(1) (see section gtags - create tag files for global.) at the root of the source tree. For example, if you want to browse the source code of Vi editor in FreeBSD, please move to the source directory and invoke gtags(1).

首先必须在源码树根目录执行 gtags,比如,如果想浏览 FreeBSD 中 vi 编辑器 i 的源码,应该在源码目录中调用 gtags。

cd /usr/src/usr.bin/vi
gtags

Gtags traverses sub-directories, picks up symbols from the source files and makes three tag files at the current directory. After this, all files and directories under the current directory are treated as a project.

gtags 遍历子目录,从源文件中提取符号,在当前目录生成三个 tag 文件。此后,当前目录中的所有文件和目录都会被当作一个项目。

ls G*
 GPATH   GRTAGS  GTAGS
  • ‘GTAGS’ definition database
  • ‘GRTAGS’ reference database
  • ‘GPATH’ path name database

You should prepare for considerable disk space for tag files. For example, Linux-2.6.32 source code requires the following disk space.

应该为 tag 文件准备相当大的磁盘空间,例如,linux-2.6.32 源码需要一次磁盘空间:

source code(Linux-2.6.32)       390MB

GPATH                             6MB
GTAGS                            81MB
GRTAGS                          202MB
-------------------------------------
total of tag files              289MB

2.2 Basic usage

2.3 Applied usage

  • You can customize a set of candidate files to be tagged.

    可以定制将要标记的候选文件:

    find . -type f -print >/tmp/list     # make a file set
    vi /tmp/list                         # customize the file set
    gtags -f /tmp/list
    
  • If your source files are on a read-only device, such as CDROM, then you cannot make tag files at the root of the source tree. In such case, you can make tag files in another place using GTAGSROOT environment variable.

    如果源文件在只读设备上,比如 CDROM,这样不能在源码树的根目录生成 tag 文件。这种情况下,可以通过 GTAGSROOT 环境变量在别的地方生成 tag 文件。

    mkdir /var/dbpath
    cd /cdrom/src                 # the root of source tree
    gtags /var/dbpath             # make tag files in /var/dbpath
    export GTAGSROOT=`pwd`
    export GTAGSDBPATH=/var/dbpath
    global func
    

    There is another method for it. Since global(1) locates tag files also in ‘/usr/obj’ + <current directory>, you can setup like follows: It is ’obj’ directory.

    还有另外一种方法。因为 global 还会在‘/usr/obj’ + <current directory>定位 tag 文件,所以可以设置如下:它就是‘obj’目录。

    cd /cdrom/src                 # the root of source tree
    mkdir -p /usr/obj/cdrom/src
    gtags /usr/obj/cdrom/src      # make tag files in /usr/obj/cdrom/src
    global func
    

    The ‘-O, –objdir’ option does it automatically for you.

    选项‘-O, –objdir’自动作这些。

    The path of obj directory can be changed by environment variable MAKEOBJDIRPREFIX.

    可以通过环境变量 MAKEOBJDIRPREFIX 改版 obj 目录路径。

  • If you want to locate symbols that are not defined in the source tree, then you can specify library directories with GTAGSLIBPATH environment variable.

    如果定位的符号不再源码树中,可以通过环境变量 GTAGSLIBPATH 指定库目录。

    You should execute gtags(1) at each directory in the GTAGSLIBPATH. If ‘GTAGS’ is not found there, global ignores such directories.

    应该在 GTAGSLIBPATH 的每个目录执行 gtags。如果 GTAGS 没有找到,global 会忽略该目录。

    $ pwd
    /develop/src/mh                 # this is a source project
    $ gtags
    $ ls G*TAGS
    GRTAGS  GTAGS
    $ global mhl
    uip/mhlsbr.c                    # mhl() is found
    $ global strlen                 # strlen() is not found
    $ (cd /usr/src/lib; gtags)      # library source
    $ (cd /usr/src/sys; gtags)      # kernel source
    $ export GTAGSLIBPATH=/usr/src/lib:/usr/src/sys
    $ global strlen
    ../../../usr/src/lib/libc/string/strlen.c  # found in library
    $ global access
    ../../../usr/src/sys/kern/vfs_syscalls.c   # found in kernel
    

    Or, you can take a more straightforward way to do the same thing. In the following example, we treat as if the system library and the kernel are part of our project.

    或者可以更直接的方式作同样的事情。下面的例子中,我们认为系统库和 kernel 是我们项目的一部分。

    $ ln -s /usr/src/lib .
    $ ln -s /usr/src/sys .
    $ gtags
    $ global strlen
    lib/libc/string/strlen.c
    $ global access
    sys/kern/vfs_syscalls.c
    
  • If you forget symbol names, you can use the ‘-c’ (complete) command.

    如果忘记符号名字,可以使用‘-c’(补全)命令

    $ global -c kmem                # maybe k..k.. kmem..
    kmem_alloc
    kmem_alloc_pageable
    kmem_alloc_wait
    kmem_free
    kmem_free_wakeup
    kmem_init
    kmem_malloc
    kmem_suballoc                   # This is what I need!
    $ global kmem_suballoc
    ../vm/vm_kern.c
    
  • You can use the ‘-c’ command with the complete command in the shell.

    shell 中‘-c’命令和 complete 命令一起使用。

    In Bash:

    $ funcs()
    > {
    >         local cur
    >         cur=${COMP_WORDS[COMP_CWORD]}
    >         COMPREPLY=(`global -c $cur`)
    > }
    $ complete -F funcs global
    $ global kmem_<TAB><TAB>
    kmem_alloc           kmem_alloc_wait      kmem_init
    kmem_alloc_nofault   kmem_free            kmem_malloc
    kmem_alloc_pageable  kmem_free_wakeup     kmem_suballoc
    $ global kmem_s<TAB>
    $ global kmem_suballoc
    ../vm/vm_kern.c
    

    If you like input completion, you should try globash (see section Global facility for Bash). It supports you in a suitable way without any preparation.

    如果想进行输入补全,实施 globash,不用任何准备就可以合适的方式支持。

  • You can edit all files which have specified tags by typing one command. For example:

    通过一个命令可以编辑包含指定 tag 的所有文件。例如:

       $ vi `global func1`     # edit fileB.c
    
  • If you want to browse many files in order, do the following:

    如果想顺序浏览很多文件,这么作:

    $ global -xr fork | awk '{printf "view +%s %s\n",$2,$3}'
    view +650 ../dev/aic7xxx/aic7xxx_asm.c
    view +250 ibcs2/ibcs2_misc.c
    view +401 linux/linux_misc.c
    view +310 ../kern/init_main.c
    view +318 ../kern/init_main.c
    view +336 ../kern/init_main.c
    view +351 ../kern/init_main.c
    $ !! | sh            # from now on, go to next tag with 'ZZ'.
    

3 Various applications

3.1 Global facility for Bash

3.2 Less using GLOBAL

3.3 Nvi-1.81.5 using GLOBAL

3.4 Elvis using GLOBAL

3.5 Vim using GLOBAL

3.6 Extended Emacs using GLOBAL

You can use GLOBAL as the tag system of Emacs editor instead of etags.

GLOBAL 替代 etags 作为 Emacs 的 tag 系统。

3.6.1 Features

  • You can use most of GLOBAL’s facilities from the editor.

    可以从编辑器中使用 GLOBAL 的大部分功能。

  • More intelligent recognition of the current token and its type.

    更智能识别当前 token 和它的类型。

  • Tag completion is available for input tag name.

    tag 补全可用于输入 tag 名字。

  • Mouse is supported.

    支持鼠标。

3.6.2 Preparation

First, do the preparation of global. See section Preparation.

首先,完成 global 的准备工作。

Second, to use global from Emacs, you need to load the ‘gtags.el’ and execute gtags-mode function in it.

其次,为了在 emacs 中使用 global,需要载入‘gtags.el’并执行 gtags-mode 函数。

Write the call to autoload function to your ‘$HOME/.emacs’, start Emacs and execute gtags-mode function. If you put ‘gtags.el’ in a directory other than the standard macro directory, you need to add it to load-path.

在‘$HOME/.emacs’中编写自动加载汉书,启动 emacs 并执行 gtags-mode 函数。

$HOME/.emacs
+------------------------------------------------------p
|(setq load-path (cons "/home/owner/global" load-path))
|(autoload 'gtags-mode "gtags" "" t)

$ emacs

|
|J_:-----Mule: *scratch*       (Lisp Interaction)--L16--All----
|M-x gtags-mode[RET]
+------------------------------------------------------

If you want to get into gtags-mode whenever you get into c-mode then you can append the following code to your ‘$HOME/.emacs’.

(setq c-mode-hook
      '(lambda ()
         (gtags-mode 1)
         ))

About key mappings, please see the comment of gtags.el.

3.6.3 Usage

  • To go to func1, invoke gtags-find-tag and you can see a prompt in the mini-buffer. Then input the tag name.

        Find tag: func1			<- 'Find tag: ' is a prompt
    
  • To go to the referenced point of func1, invoke gtags-find-rtag.

        Find tag (reference): func1
    
  • Tag name completion is available.

    Find tag: fuTAB
    
    Find tag: func1                     <- 'nc1' is appended by emacs
    
  • If a number of tags are located, Emacs goes into GTAGS SELECT MODE like this:

    +-------------------------------------------------------------
    |main             347 i386/isa/ultra14f.c main()
    |main             128 kern/init_main.c   main(framep)
    |main             104 netiso/clnp_debug.c main()
    |main             164 netiso/xebec/main.c main(argc, argv)
    |
    |
    |
    |
    |
    |J_:--%*-Mule: *scratch*       (Gtags Select)--L1--All----
    |[GTAGS SELECT MODE] 4 lines
    +-------------------------------------------------------------
    

    Please select a tag line by any Emacs command and press <RET>, and you can go to the tag’s point. When you want to go to the next or previous tag, please return to the above mode with gtags-pop-stack and reselect.

    You can customize the path style in this mode by setting gtags-path-style variable.

    • root

      relative from the root of the project (Default)

    • relative

      relative from the current directory

    • absolute

      absolute (relative from the system root directory)

    There are two methods to set this variable:

    • You can change it dynamically using the customize command of Emacs. You will find the entry in the Programming/Tools/Gtags group.
    • You can change it when Emacs is loaded using ‘.emacs’ file like this:

      (setq gtags-mode-hook
            '(lambda ()
               (setq gtags-path-style 'relative)))
      
  • gtags-find-tag-from-here command is available.

    If current token is a definition, it is equivalent to Find tag (reference): current-token<RET>, otherwise it is equivalent to Find tag: current-token<RET>.

  • To locate symbols which are not defined in ‘GTAGS’, try gtags-find-symbol.

    Find symbol: lbolt <- 'Find symbol:' is a prompt

  • To locate strings, try gtags-find-with-grep.

    Find pattern: Copyright

  • You can use POSIX regular expressions.

    Find tag: ^put_ <- locate tags starting with 'put_'

  • Mouse command is available.

    If you use X version Emacs, try the following:

    Move the mouse cursor to a symbol name and click the middle button, and you can go to the point of the definitions, or to its references, depending on the context. In ’GTAGS SELECT MODE’, move the mouse cursor to a line and click the center button.

    To return to the previous position, click the right button.

3.7 Gtags-cscope

3.8 Hypertext generator

3.9 Doxygen using GLOBAL

4 Other topics

4.1 How to configure GLOBAL

You can customize GLOBAL using configuration file.

可以通过配置文件配置 GLOBAL。

# cp gtags.conf /etc/gtags.conf         # system wide config file.
# vi /etc/gtags.conf

$ cp gtags.conf $HOME/.globalrc         # personal config file.
$ vi $HOME/.globalrc

If ‘$HOME/.globalrc’ exists then GLOBAL uses it; else if ‘/etc/gtags.conf’ exists then GLOBAL uses it; otherwise default value is used. The format of ‘gtags.conf’ resembles termcap(5). By default, ’default’ target is used. About the capabilities, please see each command manual. See section Command References.

4.2 Plug-in parser

You can write a new parser for gtags(1).

Command layer plug-in parser was abolished. Please write function layer plug-in parser instead. See ‘plugin-factory/’ to discover the function layer plug-in parser.

You can use Exuberant ctags as a plug-in parser too. This requires Exuberant ctags version 5.5 or later.

# Installation of GLOBAL
# It assumed that ctags command is installed in '/usr/local/bin'.

$ ./configure --with-exuberant-ctags=/usr/local/bin/ctags
$ make
$ sudo make install

# Executing of gtags
# It assumed that GLOBAL is installed in '/usr/local'.

$ export GTAGSCONF=/usr/local/share/gtags/gtags.conf
$ export GTAGSLABEL=ctags
$ gtags                         # gtags invokes Exuberant Ctags internally

4.3 Incremental updating

Modifying some source files, you need not remake the entire tag files. Instead, you can use incremental updating facility (‘-u’ option).

$ gtags
$ cd kernel
$ vi user.c                             # modify user.c
...
:wq
$ global -vu                            # -v means verbose
[Sat May 29 00:31:41 JST 2010] Gtags started.
Tag found in '/usr/local/src/linux-2.6.32'.
Incremental updating.
[Sat May 29 00:31:43 JST 2010] Updating 'GTAGS' and 'GRTAGS'.
[1/1] deleting tags of kernel/user.c
[1/1] extracting tags of kernel/user.c
Global databases have been modified.
[Sat May 29 00:31:51 JST 2010] Done.

$ global -vu                            # try again
[Sat May 29 00:33:16 JST 2010] Gtags started.
Tag found in '/usr/local/src/linux-2.6.32'.
Incremental updating.
Global databases are up to date.       # do nothing
[Sat May 29 00:33:19 JST 2010] Done.

5 Command References

5.1 global - print locations of given symbols

5.2 gtags - create tag files for global.

5.3 htags - generate a hypertext from a set of source files.

5.4 htags-server - start a private Web/CGI server for hyper-text

5.5 gozilla - force mozilla to display specified part of a source file.

5.6 gtags-cscope - interactively examine a C program.

5.7 globash - a special shell for GLOBAL using GNU bash.

Author: lsl

Created: 2016-08-07 Sun 19:30

Validate