给go项目生成TAGS文件

本文的go项目特指包含go开发工具和程序库的代码,获取方式参见这里

go项目包含多种编程语言写成的代码,如C,汇编,go等等,甚至包括C和go的混合体(文件后缀名为goc)。其中的C也不是标准的C,而是被称为Plan 9 C,其中会影响到etags的就是它使用unicode中的middle dot作为symbol名字的一部分,如runtime·makechan_c。它实际是一个函数名,感觉上runtime像是一个名字空间。

让etags认识middle dot的方法很简单,只需修改emacs/lib-src/etags.c,在mitk指向的字符串最后加上它就可以了。如下:

*midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789·";

在Emacs里输入middle dot的方法是:C-x 8 RET MIDDLE DOT RET。或者直接从某个源文件里面复制。

然后重新编译

$ cd emacs/lib-src/
$ make etags

现在,就可以使用如下脚本给go项目生成TAGS文件了。

#!/usr/bin/env bash

SRC_DIR=$1

if [ ! -e "$SRC_DIR/src/all.bash" ]
then
    echo "\`$SRC_DIR' is not top directory of go source code"
    exit 1
fi

pushd "$SRC_DIR"

find src -name "*.go" | \
etags --language=none \
    --regex='/type[ \t]+[^ \t]+[ \t]/' \
    --regex='/func[ \t]+[^( \t]+[( \t]/' \
    --regex='/func[ \t]+([ \t]*[^( \t]*[ \t]+\*?\([^) \t]+\)[ \t]*)[ \t]*\([^( \t]+\)[( \t]/\1.\2/' -
find src -name "*.[hc]" | etags -a -
find src -name "*.goc" | etags --language=c -a -
find src -name "*.s" | etags -a --language=none \
    --regex='/TEXT [^(]+/' -
find include -name "*.h" | etags -a -
popd

hard link陷阱

先看一系列操作:

$ echo "A" >A
$ echo "BB" >B
$ ln A C
$ ls -l -i
total 12
2056743 -rw-rw-r-- 2 liang liang 2 2011-12-31 10:28 A
2059789 -rw-rw-r-- 1 liang liang 3 2011-12-31 10:28 B
2056743 -rw-rw-r-- 2 liang liang 2 2011-12-31 10:28 C
$ cp B A
$ ls -l -i
total 12
2056743 -rw-rw-r-- 2 liang liang 3 2011-12-31 10:28 A
2059789 -rw-rw-r-- 1 liang liang 3 2011-12-31 10:28 B
2056743 -rw-rw-r-- 2 liang liang 3 2011-12-31 10:28 C
$ cat *
BB
BB
BB

你会发现,当我们用文件B覆盖文件A的时候,文件C的内容也变了。

这种情况是在编译binutils时使用--enable-gold=default这个configure选项时出现的。使用这个选项,我们会得到三个linker,文件名分别为ld, ld.bfdld.gold,其中ldld.gold的硬链接,即如上例中的AC。在这种情况下,如果想尝试BFD ld,那么不能直接使用ld.bfd覆盖ld,否则就会出现上面的情况,即ld.gold实际上也被改变为ld.bfd,而真正的ld.gold就没有了。

这种情况如果不是特别留意,很难发现,会误以为只要用ld.gold覆盖ld,就可以恢复使用Gold作为linker,其实还是在使用BFD ld。