`
weiyinchao88
  • 浏览: 1173875 次
文章分类
社区版块
存档分类
最新评论

GCC源代码阅读

 
阅读更多

获取GCC源代码

阅读源代码的第一步是获取源代码,巧妇难为无米之炊嘛!

使用以下任意方法均可获得gcc源代码:

  1. svn checkout svn://gcc.gnu.org/svn/gcc/trunk SomeLocalDir (摘自http://gcc.gnu.org/svn.html
  2. git clone git://gcc.gnu.org/git/gcc.git(摘自http://gcc.gnu.org/git/?p=gcc.git;a=summary

需要注意的是,第二种方法得到的代码并非是svn的所有历史镜像。因为gcc的svn分支不是全部位于svn://gcc.gnu.org/svn/gcc/branches/这一层,其中如redhat或者google等实际起到名字空间的作用,再下一层才是真正的分支内容,然而svn到git转换的脚本不能识别这种情况,因此所有这类位于第二层的分支都不存在于git镜像中。

当然对于初学者来说并不重要,我们只要盯住一个版本看就好了,比如4.5.2或者4.4.5(原本想等4.6发布之后再开始这个学习系列,目前看来一半时是等不到了)。由于我之前在4.4.5上有一点积累,因此如没有特别说明,这一系列的心得都是通过阅读4.4.5的代码而来。

使用源代码交叉索引工具

拿到源代码之后,建议使用代码交叉索引工具生成索引,方便阅读。常用的有etags(或者ctags)和cscope。

etags

gcc的Makefile里有生成TAGS文件的target,可以直接在编译目录下生成,如

$ mkdir build
$ cd build
$ ../gcc/configure --enable-languages=c,c++,lto
$ make
$ make -k etags # OR `make -k tags'

在Emacs里加载TAGS文件的方法是:M-x visit-tags-table

cscope

cscope的配置也不复杂,以下是在Ubuntu 10.10下安装配置步骤

$ sudo apt-get install cscope cscope-el
$ cd gcc
$ gcc-cscope.sh

gcc-cscope.sh脚本内容如下

#!/bin/bash

BUILD_DIR=${1:-../build/gcc}
cscope-files.sh libiberty gcc include gcc/config/arm $BUILD_DIR >cscope.files
if [ -f cscope.files ]
then
    cscope -b -q -k
else
    echo "cscope.files not found at $PWD."
    exit 1
fi

由于gcc的部分代码是在编译期生成的,所以除了索引源代码目录下的文件,还要索引编译目录下的文件(对应于BUILD_DIR这个变量所制订的目录,缺省为build/gcc,也可以通过参数使用其它目录)。

由于gcc支持多种硬件平台,为避免混淆,我只选择了自己关心的ARM部分代码,其它后端代码忽略。

cscope-files.sh脚本内容如下:

#!/bin/bash

for dir in "$@"
do
    find "$dir" -maxdepth 1 -iname "*.[hc]" -type f
done

要想在Emacs里面使用cscope索引结果,需要安装cscope-el软件包,并把下面一行代码加入Emacs配置文件

(require 'xcscope)

具体使用方法可以参见/usr/share/emacs/site-lisp/xcscope.el文件内的注释。

下载gcc源代码,编译通过,测试hello world之后,就可以开始认真阅读它的实现了。

通常我们阅读的源代码,是开发过程中某一时刻的快照,在特定情况下,我们不仅需要理解它的当前实现方式,还要了解它的发展过程和原因。这时,我们可以借助版本管理工具、ChangeLog文件和邮件列表,来了解开发历史。

取决于获取源代码的方式,可以使用的版本管理工具有subversion和git,熟练使用命令行工具或者图形化客户端是必须的,如果能和开发环境无缝结合就更完美了。Emacs默认的VC软件包支持多种版本管理工具,包括subversion和git。VC的操作对象是文件,如果想要了解整个项目的情况,可以安装psvn和magit。

ChangeLog是个很有趣的东西,我一度对它的作用不太理解。有了版本控制工具,还要ChangeLog做啥?!而且ChangeLog的内容也很枯燥,它只记录了源代码的物理变化,比如增加了一个变量,并在哪个函数里使用;删除一个宏;或者改变函数调用关系等等。它并不记录做出这些改变的目的或原因。后来经jzhang918介绍,终于明白它对于版本管理工具的补充作用。通常,版本工具的操作对象是文件,因此,如果想知道某个函数(或者某个变量)发生了哪些变化,则相当棘手,ChangeLog的作用便在于此。

仅有历史版本和ChangeLog还是不够的,它们缺少了一项非常重要的信息——为什么要做这样的修改。一般来说,最好能在提交日志上说明,但很少有gcc的开发者这么做,所以,就要靠邮件列表来帮忙了。通常来讲,在提交修改之前,都需要把patch发到gcc开发者所用的邮件列表上,供maintainer检查,通过后才能提交。在邮件里,作者会讲一点来龙去脉,不然maintainer一头雾水,patch就无法通过了。

学习GCC源代码,离不开各种参考资料,如论文、wiki、手册和散落在邮件列表里面的讨论。

如果没有理论背景知识,想从GCC源代码里看出它想要做什么,以及在做什么,是很困难的。因此,学习GCC实现的过程,必然伴随着不断地阅读论文。如果注释里面提到了参考论文(或书籍)的名字,不妨直接找来看看。另外一个非常重要的内容就是gcc summit,论文下载地址为http://gcc.gnu.org/wiki#GCC_Summit_Proceedings,包括从2003年至今的所有论文。

gcc summit的论文不涉及太多的细节,所以看起来不像其它论文那么头疼,但是要学习具体的算法和实现,还是要找来相应的论文,啃硬骨头。论文看多了,如何管理也是个问题,不然看了等于白看,一会儿就还给作者了。尝试了两个网站CiteULikeConnotea,都不理想,似乎更像是社会化书签服务,对于我一地的PDF毫无帮助。最后还是用orgmode记录,以后再把RefTex集成进来

要了解GCC的实现细节,还要看手册,Ubuntu下的安装方式如下:

sudo apt-get install gcc-doc

其中包括两个手册——使用手册和内部实现手册,查看方式分别为:

info gcc
info gccint

手册不适合从头到尾看下来,需要的时候查找相应内容学习就可以了,最多粗读一遍获得大概的印象,依我的经验,基本就是看了后面忘了前面,反而是遇到问题再来查找更有针对性、更容易理解。由于gccint始终处于不完整状态,所以也不要期望太多,看代码是必不可少了。

手册的在线地址为http://gcc.gnu.org/onlinedocs/

最后的信息源就是gcc wiki邮件列表了,由于时效性的问题,上面的内容是否还适用,需要个人自行判断。邮件列表有多个,我个人关注的是gcc和gcc-patches,


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics