GCC
,全稱GNU Compiler Collection,是一套GNU開發(fā)的編譯器環(huán)境,它的創(chuàng)始人便是大名鼎鼎的Richard.M.Stallman。最初GCC剛開始開發(fā)時,它還叫做GNU C Compiler,隨著開發(fā)的深入,GCC很快得到了擴展,不僅可以支持C語言,還可以處理C++,Pascal,Object-C,Java以及Ada等其他語言。目前,GCC不僅是GNU的官方編譯器,也成為編譯和創(chuàng)建其他操作系統(tǒng)的編譯器,包括BSD家族以及MAC OS X等。另外,GCC也是跨平臺交叉編譯的首選,它不僅支持Intel的x86系列,同時也支持MIPS,ARM,PowerPC,SPARC等等處理器。可以這么說,即使GCC不是世界上效率最高的編譯器,它也一定是世界上最全面的編譯器。
1. GCC簡介
我們先回到一個常識性的問題,什么是編譯器呢?簡單地說,編譯器可以看作是一個語言翻譯器。就像把中文翻譯成英語一樣,編譯器可以把高級語言翻譯成計算機能夠執(zhí)行的機器語言。這樣看來,GCC可以算得上是一個精通多國語言的高級翻譯官了。
最簡單的GCC使用指令如下所示:
gcc hello.c -o hello
GCC接受hello.c作為輸入,最后產(chǎn)生目標可執(zhí)行代碼hello。這個簡單的流程實際上經(jīng)歷了很多步驟,如下圖所示:
雖然我們只用了一條命令就完成了編譯,但實際上gcc命令依次呼叫了cpp,gcc自己,gas以及l(fā)d來進行完整的編譯流程,最后生成最終的可執(zhí)行文件hello。
下面我們看一下分解動作:
cpp hello.c > hello.i
gcc -S hello.i
as hello.s -o hello.o
ld -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i686-linux-gnu/4.4.5/crtbegin.o -L/usr/lib/gcc/i686-linux-gnu/4.4.5 hello.o -lgcc -lgcc_eh -lc /usr/lib/gcc/i686-linux-gnu/4.4.5/crtend.o /usr/lib/crtn.o -o hello
看完這些步驟有沒有暈頭轉(zhuǎn)向的感覺呢?對于普通的用戶來說,還是讓GCC幫我們做這些事情比較好。
對于如何學(xué)習(xí)使用GCC,可以參考GCC官方的手冊,如果大家覺得官方的手冊太羅嗦,我這里推薦一本GCC的入門書籍《
An Introduction to GCC》,這本書詳盡的介紹了GCC的使用方法,內(nèi)容淺顯易懂,很適合初學(xué)者。
2. GCC強大的背后
學(xué)過編譯原理這門課程的同學(xué)對下面這副圖應(yīng)該很熟悉,這是經(jīng)典的編譯流程。
GCC作為經(jīng)典的編譯器,自然也是遵循這個教科書流程(實際GCC的處理更復(fù)雜點,但本質(zhì)上是一樣的)。我們先簡化一下上面這幅圖,以中間代碼為分界,前面的詞法分析、語法分析、語義分析我們把它稱之為前端處理,后面的優(yōu)化和目標代碼生成我們稱之為后端處理。
試想一下,是否可以為不同的高級語言單獨寫一個前端,然后為不同的處理器架構(gòu)單獨寫一個后端呢?
GCC基本上也是這么實現(xiàn)的,不過不要誤會,并沒有一個統(tǒng)一的gcc執(zhí)行程序能夠處理如此多的前端和后端,每個語言的編譯器都是一個獨立的程序(如C語言的編譯器是gcc,C++的編譯器是g++),而不同的后端也要對應(yīng)不同的可執(zhí)行程序。你可以下載單獨的一份GCC源代碼,通過不同的configure來編譯自己需要的編譯器。
而且,編譯器的實現(xiàn)也比上圖要復(fù)雜的多,前端的主要功能是產(chǎn)生一個可供后端處理的語法樹,而語法樹結(jié)構(gòu)實際上很難與處理器架構(gòu)脫鉤,這些都是編譯器應(yīng)用中需要解決的問題。
GCC強大的真正原因是什么?是因為它支持了眾多的前端和后端嗎?這些都不過是一個表象而已。GCC是一款真正自由的編譯器,我們可以隨時把代碼拿過來修改以實現(xiàn)自己需要的功能。如果你的硬件平臺增加了一些指令,而普通的編譯器并不能產(chǎn)生這些指令怎么辦?在GCC后端添加這些指令吧。如果你覺得C語言用的不太順手,想給它添加一些功能怎么辦?修改GCC的前端吧。因為有了GCC,我們才擁有這些自由,以及迅速實現(xiàn)自己想法的能力,而這些才是GCC強大背后的基礎(chǔ)。
2010年1月份的時候,Google的Go語言前端被允許進入GCC編譯器家族,GCC更加強大了。
3. GCC的多樣性
GCC因為其靈活性被應(yīng)用到了很多領(lǐng)域和系統(tǒng),從PC上的開發(fā)到嵌入式開發(fā),都可以見到GCC的影子。
3.1 PC開發(fā)
我們先看看PC。MAC自從投入Intel的懷抱,是否也可以看作是一種PC呢?
Linux
Linux系統(tǒng)應(yīng)該是GCC的主戰(zhàn)場,但也是最沒必要去說的一個系統(tǒng),除了GCC,難道我們還有更好的選擇嗎?Linux內(nèi)核、Apache服務(wù)器、MySQL數(shù)據(jù)庫,等等一系列偉大的作品都是通過GCC來構(gòu)建的,GCC可以說是GNU/Linux系統(tǒng)的基石。
MAC OS X
MAC OS X也是GCC的重度用戶,其應(yīng)用程序開發(fā)環(huán)境Cocoa就是使用的GCC,所以在MAC OS X下開發(fā)也是離不開GCC的。
Windows
現(xiàn)在在Windows下開發(fā)C/C++程序一般都是用微軟的編譯器,當年的Borland已經(jīng)成為傳說。但是如果你不想付錢的話,也可以考慮Windows下的GCC。
在Windows下體驗GCC最常用的有兩種方式:一是在Cygwin下使用GCC,另外一種是使用MinGW。
Cygwin
是一個自由軟件的集合,最初由Cygnus Solutions開發(fā),目的是在Windows系統(tǒng)上運行類Unix的軟件。通過Cygwin編譯的程序可以在Windows上運行,但必須使用cygwin.dll。
MinGW
(Minimalist GNU for Windows),是將GNU開發(fā)工具移植到Windows平臺的產(chǎn)物,包括一系列頭文件、庫和可執(zhí)行文件,用MinGW開發(fā)的程序不需要額外的第三方DLL就可以直接在Windows上運行。Nokia的圖形開發(fā)包QT在Windows下就是調(diào)用MinGW來編譯的。
DOS
在DOS系統(tǒng)下也是可以用GCC的,國內(nèi)的DOS開發(fā)者可能更熟悉Turbo C或者Open Watcom,GCC的DOS版本
DJGPP其實也是32位DOS程序開發(fā)的主流環(huán)境之一。最初DJGPP的發(fā)起人DJ Delorie曾經(jīng)詢問過Richard Stallman,F(xiàn)SF是否考慮過把GCC移植到MS-DOS下,當時Richard的回答是GCC太龐大,而MS-DOS只不過是個16位的操作系統(tǒng),所以官方并沒有考慮這件事。DJ Delorie并沒有因此而退縮,最終給我們帶來了這個優(yōu)秀的開發(fā)平臺。DJGPP剛開始開發(fā)時叫做djgcc,在引入了C++之后改為現(xiàn)在這個名字(DJ's GNU Programming Platform)。
3.2 嵌入式開發(fā)
對于嵌入式開發(fā)領(lǐng)域來說,因為開發(fā)板的能力限制,是無法運行編譯環(huán)境的,這樣就需要在PC上通過交叉編譯來生成目標可執(zhí)行程序,GCC的高度靈活性在嵌入式開發(fā)上發(fā)揮了極大的作用。
Android
看看當今最火的移動平臺Android,就是完全用GCC來構(gòu)建的,請注意,這里指的不是Android應(yīng)用程序,Android下的應(yīng)用程序是運行在Dalvik虛擬機上的Java程序。
iOS
Apple的iOS應(yīng)用程序開發(fā)也是用Cocoa來進行,這怎么會離開GCC呢?
MeeGo/Symbian
在Apple和Google的沖擊下,Nokia似乎已經(jīng)日薄西山了,但對于中國國情來說,真的是這樣嗎?iPhone高高在上,擁有者只會是少數(shù),Google退出中國之后,Android Market很難在國內(nèi)有所作為,再加上Nokia手機一貫皮實的口碑,現(xiàn)在的Symbian以及將來的MeeGo的保有量應(yīng)該不會低。Nokia已經(jīng)把Symbian和MeeGo的開發(fā)環(huán)境統(tǒng)一到QT上了,這里依然是GCC的一畝三分田。
GCC是強大的,但它并不是一個人在戰(zhàn)斗,在它的背后站著
GNU工具鏈,包括make,GCC,Binutils,GDB等一系列工具,這些工具之間是相輔相成的,只有把它們組合起來使用才能發(fā)揮其最大的威力。