前面一篇已經簡單的介紹了如何利用gcc編譯c源代碼,這篇說一下gcc的具體編譯過程
- 預處理
預處理的工作主要是處理#include語句等,然后生成*.i文件。如果不加參數“-o *.i”,則會將預處理的結果輸出到標準輸出。
gcc -E *.c -o *.i #使用gcc的E參數進行預處理
cpp *c - o *.i #使用cpp命令進行預處理
這兩條命令預處理的結果一樣,因為gcc使用-E參數實際上也是調用了cpp指令。
2.生成匯編代碼
gcc -S *c -o *.s #將C代碼匯編為匯編語言代碼
gcc -S *.i -o *.s #將i文件匯編為匯編語言代碼
3.編譯
gcc -c *.c -o *.o
gcc -c *.s -o *o
as *.s -o *.o
cc -c *.c -o *.o
4.鏈接
gcc *.o -o *out
GCC高級技巧
1.指定頭文件位置
一是在源碼中指定頭文件的絕對路徑,簡單直觀但缺乏靈活性,二是在編譯時使用“-I”參數來指定頭文件的路徑,實際工作中,一般選擇第二種。
使用第二種方法將resolv.c編譯為resolv.out的命令如下:
gcc resolv.c -I /home/myname/code/header -o resolv.out 如果找不到會按照代碼所在目錄或系統目錄尋找頭文件
gcc resolv.c -I /home/myname/code/header -I /home/myname/code/header2 -o resolv.out 多個路徑
2.定義符號常量
在代碼中會使用一些常量來控制程序的行為,如#define WIRELESS 211 等等一系列,怎么來檢驗定義了符號常量與為定義符號常量的區別,一般在編譯時使用-D參數來指定符號常量,命令如下:gcc -D WIRELESS -I /home/myname/code/header resolv.c -o resolv.out
3.定義警告級別
最常用的警告選項是-Wall選項。其意思是warning all。使用如下命令顯示特定警告信息來編譯test.c,命令如下:
gcc -Wall test.c -o test
4.其他GCC選項
gcc [option] [filename]
- -c:只將源代碼編譯為以.o為后綴的目標文件,而不是直接將這些文件連接可執行文件。通常用于不包含主程序(man函數)的子程序代碼。
- -o:filename: 指定輸出文件名。如果不用這個選項,gcc會將文件輸出到a.out,而不管輸出文件的類型
- -g:產生調試信息。如果要使用gdb進行調式,則必須使用該選項。但是該選項所產生的調式符號,并不能被其他調式器識別。
- -O:在程序編譯、連接過程中對代碼進行優化。
- -O2:比-O更好的優化編譯、連接。
- -L dir:在程序連接時,會首先在dir目錄尋找類庫文件,然后在系統預設路徑中尋找類庫。也可以使用多個-L參數指定多個類庫存放的目錄。
- -lname:在程序連接時加載名為libname.a的函數庫。如-lmath 表示連接名為libmath.a的數學函數庫。
- --sysboot=dir:讓目錄dir作為頭文件和庫文件的根目錄
- -B dir:將目錄dir添加到編譯器的搜索路徑中。
- -b:指定gcc編譯的目標機器架構,如ARM、DEC、GNU/Linux、IA64、MIPS等,這也可以看出gcc的超級跨平臺性。
- -V n1.n2:使用n1.n2指定版本的gcc進行編譯
- -E:僅作預處理,不能進行編譯等工作,生成i文件
- -S:將源碼編譯為匯編語言代碼
- -x lang:將源代碼依照特定語言進行編譯,可以取得值包括但不限于C、C++、Objective-C、Objective-C++、Assembler、Ada、java等。在一系列的編譯中,該選項會一直保持,知道另一個-x lang出現,指定另一種編譯語言。如果是none,意味著讓gcc一句文件的后綴來自動判斷語言種類。