GCC源代码阅读
獲取GCC源代碼
閱讀源代碼的第一步是獲取源代碼,巧婦難為無米之炊嘛!
使用以下任意方法均可獲得gcc源代碼:
需要注意的是,第二種方法得到的代碼并非是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.shgcc-cscope.sh腳本內容如下
#!/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的部分代碼是在編譯期生成的,所以除了索引源代碼目錄下的文件,還要索引編譯目錄下的文件(對應于BUILD_DIR這個變量所制訂的目錄,缺省為build/gcc,也可以通過參數使用其它目錄)。
由于gcc支持多種硬件平臺,為避免混淆,我只選擇了自己關心的ARM部分代碼,其它后端代碼忽略。
cscope-files.sh腳本內容如下:
#!/bin/bashfor dir in "$@" dofind "$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的論文不涉及太多的細節,所以看起來不像其它論文那么頭疼,但是要學習具體的算法和實現,還是要找來相應的論文,啃硬骨頭。論文看多了,如何管理也是個問題,不然看了等于白看,一會兒就還給作者了。嘗試了兩個網站CiteULike和Connotea,都不理想,似乎更像是社會化書簽服務,對于我一地的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,
總結
                            
                        - 上一篇: IP地址不是唯一的吗?为什么路由器的IP
 - 下一篇: asp.net发布网站的详细步骤