GCC源代码阅读
獲取GCC源代碼
閱讀源代碼的第一步是獲取源代碼,巧婦難為無米之炊嘛!
使用以下任意方法均可獲得gcc源代碼:
需要注意的是,第二種方法得到的代碼并非是svn的所有歷史鏡像。因?yàn)間cc的svn分支不是全部位于svn://gcc.gnu.org/svn/gcc/branches/這一層,其中如redhat或者google等實(shí)際起到名字空間的作用,再下一層才是真正的分支內(nèi)容,然而svn到git轉(zhuǎn)換的腳本不能識(shí)別這種情況,因此所有這類位于第二層的分支都不存在于git鏡像中。
當(dāng)然對(duì)于初學(xué)者來說并不重要,我們只要盯住一個(gè)版本看就好了,比如4.5.2或者4.4.5(原本想等4.6發(fā)布之后再開始這個(gè)學(xué)習(xí)系列,目前看來一半時(shí)是等不到了)。由于我之前在4.4.5上有一點(diǎn)積累,因此如沒有特別說明,這一系列的心得都是通過閱讀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的配置也不復(fù)雜,以下是在Ubuntu 10.10下安裝配置步驟
$ sudo apt-get install cscope cscope-el $ cd gcc $ gcc-cscope.shgcc-cscope.sh腳本內(nèi)容如下
#!/bin/bashBUILD_DIR=${1:-../build/gcc} cscope-files.sh libiberty gcc include gcc/config/arm $BUILD_DIR >cscope.files if [ -f cscope.files ] thencscope -b -q -k elseecho "cscope.files not found at $PWD."exit 1 fi由于gcc的部分代碼是在編譯期生成的,所以除了索引源代碼目錄下的文件,還要索引編譯目錄下的文件(對(duì)應(yīng)于BUILD_DIR這個(gè)變量所制訂的目錄,缺省為build/gcc,也可以通過參數(shù)使用其它目錄)。
由于gcc支持多種硬件平臺(tái),為避免混淆,我只選擇了自己關(guān)心的ARM部分代碼,其它后端代碼忽略。
cscope-files.sh腳本內(nèi)容如下:
#!/bin/bashfor dir in "$@" dofind "$dir" -maxdepth 1 -iname "*.[hc]" -type f done要想在Emacs里面使用cscope索引結(jié)果,需要安裝cscope-el軟件包,并把下面一行代碼加入Emacs配置文件
(require 'xcscope)具體使用方法可以參見/usr/share/emacs/site-lisp/xcscope.el文件內(nèi)的注釋。
下載gcc源代碼,編譯通過,測(cè)試hello world之后,就可以開始認(rèn)真閱讀它的實(shí)現(xiàn)了。
通常我們閱讀的源代碼,是開發(fā)過程中某一時(shí)刻的快照,在特定情況下,我們不僅需要理解它的當(dāng)前實(shí)現(xiàn)方式,還要了解它的發(fā)展過程和原因。這時(shí),我們可以借助版本管理工具、ChangeLog文件和郵件列表,來了解開發(fā)歷史。
取決于獲取源代碼的方式,可以使用的版本管理工具有subversion和git,熟練使用命令行工具或者圖形化客戶端是必須的,如果能和開發(fā)環(huán)境無縫結(jié)合就更完美了。Emacs默認(rèn)的VC軟件包支持多種版本管理工具,包括subversion和git。VC的操作對(duì)象是文件,如果想要了解整個(gè)項(xiàng)目的情況,可以安裝psvn和magit。
ChangeLog是個(gè)很有趣的東西,我一度對(duì)它的作用不太理解。有了版本控制工具,還要ChangeLog做啥?!而且ChangeLog的內(nèi)容也很枯燥,它只記錄了源代碼的物理變化,比如增加了一個(gè)變量,并在哪個(gè)函數(shù)里使用;刪除一個(gè)宏;或者改變函數(shù)調(diào)用關(guān)系等等。它并不記錄做出這些改變的目的或原因。后來經(jīng)jzhang918介紹,終于明白它對(duì)于版本管理工具的補(bǔ)充作用。通常,版本工具的操作對(duì)象是文件,因此,如果想知道某個(gè)函數(shù)(或者某個(gè)變量)發(fā)生了哪些變化,則相當(dāng)棘手,ChangeLog的作用便在于此。
僅有歷史版本和ChangeLog還是不夠的,它們?nèi)鄙倭艘豁?xiàng)非常重要的信息——為什么要做這樣的修改。一般來說,最好能在提交日志上說明,但很少有g(shù)cc的開發(fā)者這么做,所以,就要靠郵件列表來幫忙了。通常來講,在提交修改之前,都需要把patch發(fā)到gcc開發(fā)者所用的郵件列表上,供maintainer檢查,通過后才能提交。在郵件里,作者會(huì)講一點(diǎn)來龍去脈,不然maintainer一頭霧水,patch就無法通過了。
學(xué)習(xí)GCC源代碼,離不開各種參考資料,如論文、wiki、手冊(cè)和散落在郵件列表里面的討論。
如果沒有理論背景知識(shí),想從GCC源代碼里看出它想要做什么,以及在做什么,是很困難的。因此,學(xué)習(xí)GCC實(shí)現(xiàn)的過程,必然伴隨著不斷地閱讀論文。如果注釋里面提到了參考論文(或書籍)的名字,不妨直接找來看看。另外一個(gè)非常重要的內(nèi)容就是gcc summit,論文下載地址為http://gcc.gnu.org/wiki#GCC_Summit_Proceedings,包括從2003年至今的所有論文。
gcc summit的論文不涉及太多的細(xì)節(jié),所以看起來不像其它論文那么頭疼,但是要學(xué)習(xí)具體的算法和實(shí)現(xiàn),還是要找來相應(yīng)的論文,啃硬骨頭。論文看多了,如何管理也是個(gè)問題,不然看了等于白看,一會(huì)兒就還給作者了。嘗試了兩個(gè)網(wǎng)站CiteULike和Connotea,都不理想,似乎更像是社會(huì)化書簽服務(wù),對(duì)于我一地的PDF毫無幫助。最后還是用orgmode記錄,以后再把RefTex集成進(jìn)來。
要了解GCC的實(shí)現(xiàn)細(xì)節(jié),還要看手冊(cè),Ubuntu下的安裝方式如下:
sudo apt-get install gcc-doc其中包括兩個(gè)手冊(cè)——使用手冊(cè)和內(nèi)部實(shí)現(xiàn)手冊(cè),查看方式分別為:
info gcc info gccint手冊(cè)不適合從頭到尾看下來,需要的時(shí)候查找相應(yīng)內(nèi)容學(xué)習(xí)就可以了,最多粗讀一遍獲得大概的印象,依我的經(jīng)驗(yàn),基本就是看了后面忘了前面,反而是遇到問題再來查找更有針對(duì)性、更容易理解。由于gccint始終處于不完整狀態(tài),所以也不要期望太多,看代碼是必不可少了。
手冊(cè)的在線地址為http://gcc.gnu.org/onlinedocs/。
最后的信息源就是gcc wiki和郵件列表了,由于時(shí)效性的問題,上面的內(nèi)容是否還適用,需要個(gè)人自行判斷。郵件列表有多個(gè),我個(gè)人關(guān)注的是gcc和gcc-patches,
總結(jié)
- 上一篇: IP地址不是唯一的吗?为什么路由器的IP
- 下一篇: [转帖]H.264 RTP payloa