天天看點

GUN gcc

gun gcc

一、gcc的介紹

gcc(gnucompilercollection,gnu編譯器集合)是一套由gnu工程開發的支援多種程式設計語言的編譯器。gcc是自由軟體發展過程中的著名例子,由自由軟體基金會以gpl協定釋出。gcc是大多數類unix作業系統(如linux、bsd、macos x等)的标準的編譯器,gcc同樣适用于微軟的windows。gcc支援多種計算機體系晶片,如x86、arm,并已移植到其他多種硬體平台。gcc原名為gnu c編譯器(gnu ccompiler),因為它原本隻能處理c語言。gcc很快地擴充,并支援處理c++。後來又擴充能夠支援更多程式設計語言,如fortran、pascal、objective-c、java、ada、go等。

二、gcc編譯過程被分為四個階段

gcc首先調用cpp進行預處理,在預處理過程中,對源代碼檔案中的檔案包含(incloude)、預編譯語句進行分析。

接着調用ccl進行編譯,這個階段跟據輸入檔案生成以.o為字尾的目标檔案。彙編過程就是針對彙編語言的步驟。

調用as進行工作,一般來講,.s為字尾的彙編語言源代碼檔案和.s為字尾的彙編語言檔案經過預編譯和彙編之後會生成以.o為字尾的目标檔案。

當所有的目标檔案都生成以後,gcc就調用ld來完成最後關鍵性的工作,這個是階段性的連結。在連結階段,所有的目标檔案被安排在可執行程式中的恰當位置,同時,該程式所調用到的庫函數也從各自所在的庫中連接配接到何時的地方。

三、gcc的基本用法

gcc的基本用法是:gcc [options] [filenames]

其中,options幾十編譯器所需要的參數,filenames給出相關的檔案名稱,最常用的有以下參數。

-c,隻編譯,不連結成為可執行檔案。編譯器隻是由輸入的.c等源代碼檔案生成.o為字尾的目标檔案,通常用于編譯不包含主程式的子程式檔案。

-o,output_filename,确定輸出檔案的名稱問output_filename。同時這個名稱不能和源檔案同名。如果不給出這個選項,gcc就給出預設的可執行檔案a.out。

-g,産生符号調試工具(gun的gdb)所必要的符号資訊,要想對源代碼進行調試,就必須加入這個選項。

-o,對程式進行優化編譯、連結。采用這個選項,整個源代碼會在編譯、連結過程中進行優化處理,這樣産生的可執行檔案的執行效率可以提高,但是編譯、連結的速度就會慢一些,而且對執行檔案的調試會産生一些影響,造成一些執行效果對應源檔案代碼不一緻等一些令人“困惑”的情況。是以,一般在編譯輸出軟體發行版同時使用此選項。

-o2,比-o更好的優化編譯、連結。當然整個編譯。連結過程會更慢。

-idirname,将dirname所指出的目錄加入到程式頭檔案目錄清單中,是在預編譯過程中使用的參數。c程式中的頭檔案包含兩種情況:

#incloud<stdio.h>

預處理程式cpp在系統預設包含檔案目錄(如/usr/incloud)中搜尋相應的檔案。

#incloud”stdio.h”

cpp在目前目錄中搜尋頭檔案,這個選項作用是告訴cpp,如果在目前目錄中沒有找到需要的檔案,就到指定的dirname目錄中去尋找。在程式設計中,如果需要的這種包含檔案分别分布在不同的目錄中,就需要逐個使用-i選項給出搜尋路徑。

-ldirname,将dirname所指出的目錄加入到程式函數庫檔案的目錄清單中,是在連結過程中使用的參數,在預設情況下,連結程式ld在系統中的預設路徑中(如/usr/lib)尋找所需要的庫檔案。這個選項告訴連結程式,首先到-l指定的目錄中去尋找,然後到系統預設的路徑中去需找,如果函數庫存放在多個目錄下,就需要依次使用這個選項,給出相應的存放目錄。

-iname,連結時裝載名為libname.a的函數庫。該函數庫位于系統預設的目錄或者由-l選項确定的目錄下。

例如:

-iname,連結時裝載名為libname.a的函數庫,該函數庫位于系統預設的目錄或者 -l選項确定的目錄下,例如:-im表示連結名為libm.a的數學函數庫。

u例如:

cat test.c

#incloud < stidio.h >

int main(void)

{

printf("hello word,linuxprogramming!\n");

return 0;

}

最簡單的辦法是:

gcc test.c –o test

首選需要調用預處理程式cpp,由它負責展開在源檔案中定義的宏,并向其中插入“#incloud”語句包含的内容;接着,gcc調用ccl和as,将處理後的源代碼編譯成目标代碼;最後,gcc調用連結程式ld,把生成的目标代碼連結成一個可執行的程式,是以在預設情況下,預編譯、編譯連結一次完成。

四、編譯過程分步執行

為了更好地了解gcc的工作過程,我們可以讓在gcc工作的4個階段中的任何一個階段中停止下來。

-e 預編譯後停止下來,生成字尾為.i的預編譯檔案;

-s 彙編後聽下來,生成字尾為.s的彙編檔案;

-c 編譯後停下來,生成字尾為.o的目标檔案;

可以把上述編譯過程分為幾個步驟單獨進行,并觀察每步的運作結果,第一步是進行預編譯,使用–e參數可以讓gcc在預處理結束後停止編譯過程;

#gcc –e test.c –o test.i

gcc執行到預編譯後停下來,生成test.i的預編譯檔案。此時若檢視test.i檔案中的内容,會發現stdio.h的内容卻是都查到檔案清單中去了,而其它應當被預處理的宏定義也都做了相應的處理,下一步是将test.i編譯為目标代碼,這樣可以通過使用-c參數來完成:

#gcc –s test.c –o test.s

gcc執行到彙編後停止,生成test.s的彙編源檔案,這是一個非常重要的中間件檔案。因為在嵌入式系統中,受系統硬體自建的限制往往對目标檔案的執行效率,檔案大小都有要求,通過人工檢視彙編檔案有時往往可以找到問題所在進行人工優化。

最後一步是将生成的目标檔案連接配接成可執行檔案:

#gcc test.o –o test

對于稍微複雜的情況,比如有多個源碼檔案,需要連結庫或者有其它比較特别的要求,就要給定調檔的調用選項參數。

繼續閱讀