gcc編譯器
- GNU CC(簡稱gcc),是GUN項目中符合ANSI C標準的編譯系統(tǒng)。
- GCC不僅僅能支持 C 語言;它現(xiàn)在還支持 Ada 語言、C++ 語言、Java 語言、Objective C 語言、Pascal 語言、COBOL語言,以及支持函數(shù)式編程和邏輯編程的 Mercury 語言,等等。
- 而且gcc是一個交叉平臺編譯器,它能夠在當前CPU平臺上為多種不同體系結構的硬件平臺開發(fā)軟件,因此尤其適合在嵌入式領域的開發(fā)編譯。
gcc編譯流程分為4個步驟:- 預處理(gcc -E)、編譯(gcc -S)、匯編(gcc -c)、鏈接, gcc 選項可以簡記為“ESc”,相應的產(chǎn)出文件的后綴可以簡記為“iso”
下面具體看一下gcc是如何完成以上4個步驟的: //test.c #include int main(void) {printf('Hello World!\n');return 0;}
這個程序,一步到位的編譯指令是: gcc test.c -o test
預處理運行預處理命令: gcc -E test.c -o test.i 或 gcc -E test.c
gcc的-E選項,可以讓編譯器在預處理后停止,并輸出預處理結果。 gcc的-o選項,用于輸出處理結果到文件中。 在本例中,預處理結果就是將stdio.h 文件中的內容插入到test.c中 了。 編譯預處理之后,可直接對生成的test.i文件編譯,生成匯編代碼: gcc -S test.i -o test.s
gcc的-S選項,表示在程序編譯期間,在生成匯編代碼后,停止,-o輸出匯編代碼文件。 匯編gcc -c test.s -o test.o
鏈接鏈接階段,這里涉及一個重要的概念:函數(shù)庫 在這個程序中并沒有定義“printf”的函數(shù)實現(xiàn),且在預編譯中包含進的“stdio.h”中也只有該函數(shù)的聲明,而沒有定義函數(shù)的實現(xiàn),那么,是在哪里實現(xiàn)“printf”函數(shù)的呢? 最后的答案是:系統(tǒng)把這些函數(shù)的實現(xiàn)都放到名為libc.so.6的庫文件中去了,在沒有特別指定時,gcc會到系統(tǒng)默認的搜索路徑“/usr/lib”下進行查找,也就是鏈接到libc.so.6函數(shù)庫中去,這樣就能調用函數(shù)“printf”了,而這也正是鏈接的作用
函數(shù)庫有靜態(tài)庫和動態(tài)庫兩種 靜態(tài)庫是指編譯鏈接時,將庫文件的代碼全部加入到可執(zhí)行文件中,因此生成的文件比較大,但在運行時也就不再需要庫文件了,其后綴名通常為“.a”。動態(tài)庫與之相反,在編譯鏈接時并沒有將庫文件的代碼加入到可執(zhí)行文件中,而是在程序執(zhí)行時加載,這樣可以節(jié)省系統(tǒng)的開銷。一般動態(tài)庫的后綴名為“.so”,如前面所述的libc.so.6就是動態(tài)庫。gcc在編譯時默認使用動態(tài)庫。
對于上一小節(jié)中生成的test.o,將其與C標準輸入輸出庫進行連接,最終生成程序test: gcc test.o -o test
多個程序文件的編譯通常整個程序是由多個源文件組成的,相應地也就形成了多個編譯單元,使用GCC能夠很好地管理這些編譯單元。假設有一個由test1.c和 test2.c兩個源文件組成的程序,為了對它們進行編譯,并最終生成可執(zhí)行程序test,可以使用下面這條命令: gcc test1.c test2.c -o test
如果同時處理的文件不止一個,GCC仍然會按照預處理、編譯和鏈接的過程依次進行。如果深究起來,上面這條命令大致相當于依次執(zhí)行如下三條命令: gcc -c test1.c -o test1.ogcc -c test2.c -o test2.ogcc test1.o test2.o -o test
|