GCC - My GCC Manual
1. gcc/g++ 工作原理
1.1. gcc/g++生成可執行文件的完整步驟
預處理(preprocessing) è
編譯 (compilation) è
彙編 (assembly) è
連接 (linking)
Tips:
編譯:將預處理後的語句翻譯成彙編語言。
彙編:把彙編語言翻譯成機器語言的過程稱爲彙編。
1.2. 源文件後綴名指出語言種類和後期操作
● 非連接器(linker)階段-編譯器(compiler)階段
.c è C源程序 |
預處理,編譯,彙編 |
.C è C++源程序 |
預處理,編譯,彙編 |
.cc è C++源程序 |
預處理,編譯,彙編 |
.cxx è C++源程序 |
預處理,編譯,彙編 |
.cpp è C++源程序 |
預處理,編譯,彙編 |
.cp è C++源程序 |
預處理,編譯,彙編 |
.CPP è C++ |
預處理,編譯,彙編 |
.m è Objective-C源程序 |
預處理,編譯,彙編 |
.i è 預處理後的C文件 |
編譯,彙編 |
.ii è 預處理後的C++文件 |
編譯,彙編 |
.s è 彙編語言源程序 |
彙編 |
.S è 彙編語言源程序 |
預處理,彙編 |
.h è C預處理器文件 |
預處理 |
.hh è C預處理器文件 |
預處理 |
.H è C預處理器文件 |
預處理 |
PS:
非連接器階段處理結束講生成連接器階段的文件
● 連接器(linker)階段
.o 目標文件(Object File)
.a 歸檔庫文件(Archive File)
2. gcc/g++ 常用命令詳解
2.1. 總體選項(Overall Option)
選項 |
說明 |
實例 |
-x [language] |
● 明確指出後面輸入文件的語言類型爲language,而不是從文件名後綴得到的默認選擇。 ● 這個選項應用於後面所有的輸入文件,直到遇着下一個`-x'選項。 ● language的可選值有 ‘c’ è c語言 ‘objective-c’ è 擴展c的ObjC語言 ‘c-header’ è ‘c++’ è c++語言 ‘cpp-output’ è ‘assembler’ è 彙編語言 ‘assembler-with-cpp’ è |
|
-x none |
關閉任何對語種的明確說明,依據文件名後綴處理後面的文件(就像是從未使用過‘-x’選項)。 |
|
-c (compile) |
● 編譯或彙編源文件,但是不作連接。編譯器輸出對應於源文件的目標文件。 ● 缺省情況下, GCC通過用‘.o’替換源文件名後綴‘.c’、‘.i’、‘.s’,等等,產生目標文件名。 ● 可以使用-o選項選擇其他名字。 ● GCC忽略-c選項後面任何無法識別的輸入文件(他們不需要編譯或彙編) |
[命令] gcc -c HelloWorld.c [生成文件] HelloWorld.o
[命令] gcc -c HelloWorld.c -o HiWorld.o [生成文件] HiWorld.o |
-o [file] (output) |
● 指定輸出文件爲file。該選項不指定GCC產生什麼輸出——無論是可執行文件、目標文件、彙編文件還是預處理後的C代碼。 ● 如果沒有使用‘-o’選項,默認的輸出結果是:可執行文件爲‘a.out’。 |
[命令] gcc HelloWorld.c [生成文件] a.out
[命令] gcc HelloWorld.c [生成文件] a.out
[命令] gcc HelloWorld.c -o HelloWorld.out [生成文件] HelloWorld.out
[命令] gcc HelloWorld.o -o HelloWorld.out [生成文件] HelloWorld.out |
-S |
● 生成彙編文件。編譯後即停止,不進行彙編。對於每個輸入的非彙編語言文件,輸出文件是彙編語言文件。 ● GCC忽略任何不需要編譯的輸入文件。 |
[命令] gcc -S HelloWorld.c [生成文件] HelloWorld.s
[命令] gcc -S HelloWorld.c -o HiWorld.s [生成文件] HiWorld.s |
-E |
● 預處理後即停止,不進行編譯。預處理後的代碼送往標準輸出。 ● GCC忽略任何不需要預處理的輸入文件。 |
|
2.2. 語言選項(LANGUAGE OPTIONS)
選項 |
說明 |
實例 |
-ansi |
支持符合ANSI標準的C程序。 ● 這樣就會關閉GNU C中某些不兼容ANSI C的特性,例如asm、inline、typeof等關鍵字,以及諸如unix和vax這些表明當前系統類型的預定義宏。同時開啓不受歡迎和極少使用的ANSI trigraph特性,以及禁止‘$’成爲標識符的一部分。 ● 使用‘-ansi’選項不會自動拒絕編譯非ANSI程序,可以增加‘-pedantic’選項作爲‘-ansi’選項來實現。 ● 使用‘-ansi’選項的時候,預處理器會預定義一個__STRICT_ANSI__宏。有些頭文件關注此宏以避免聲明某些函數,或者避免定義某些宏。這些函數和宏不被ANSI標準調用——這樣就不會干擾在其他地方使用這些名字的程序了。 |
|
2.3. 預處理器選項(Preprocessor Option)
選項 |
說明 |
實例 |
2.4. 警告選項(WARNING OPTION)
選項 |
說明 |
實例 |
-w |
禁止所有警告信息。 |
|
-Wall |
打開所有警告信息。 |
|
2.5. 連接器選項(LINKER OPTION)
函數庫分爲靜態庫和動態庫兩種。靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態庫。動態庫在程序編譯時並不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態庫存在。
(1) 靜態鏈接庫
● 靜態庫文件名的命名規範是以lib爲前綴,緊接着跟靜態庫名,擴展名爲.a。例如:我們將創建的靜態庫名爲myhello,則靜態庫文件名就是libmyhello.a。在創建和使用靜態或庫時,需要注意這點。
● 無論靜態庫還是動態庫,都是由.o文件創建的。因此我們必須將源程序通過gcc將源文件先編譯成.o文件。
● 靜態鏈接庫其實是歸檔文件(Archieve File)。創建靜態庫用ar命令:
#ar crv libmyhello.a hello.o
● 使用靜態鏈接庫:
#gcc main.c libmyhello.a -o main 等價於
#gcc -o main main.c –L. –lmyhello
● 靜態庫鏈接時搜索路徑順序:
找GCC命令中的參數-L è 找gcc的環境變量LIBRARY_PATH(指定程序靜態鏈接庫文件搜索路徑) è 找內定目錄/lib /usr/lib /usr/local/lib這是當初compile gcc時寫在程序內的。
(2) 動態鏈接庫
● 動態庫文件名命名規範和靜態庫文件名命名規範類似,也是在動態庫名增加前綴lib,但其文件擴展名爲.so。例如要創建的動態庫名爲myhello,則動態庫文件名就是libmyhello.so。
● 無論靜態庫還是動態庫,都是由.o文件創建的。因此我們必須將源程序通過gcc將源文件先編譯成.o文件。
● 創建動態鏈接庫:# gcc -shared -fPCI -o libmyhello.so hello.o
● 使用動態鏈接庫:
# gcc -o hello main.c –L. –lmyhello (注意-L後面有個.表示的是當前目錄)
● 動態庫鏈接時搜索路徑順序:
找GCC命令中的參數-L è 環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑 è 配置文件/etc/ld.so.conf中指定的動態庫搜索路徑 è
默認的動態庫搜索路徑/lib èè默認的動態庫搜索路徑/usr/lib。
Tips:
當靜態庫和動態庫同名時, gcc命令將優先使用動態庫。
選項 |
說明 |
實例 |
-l [library] |
● 連接名爲library的庫文件。 ● 庫名跟真正的庫文件名的關係:拿數學庫來說——庫名是m,他的動庫文件名是libm.so,靜態庫文件名師libm.a。很容易看出把庫文件名的頭lib和尾.so去掉就是庫名了 ● 指定‘-l’選項和指定文件名的唯一區別是, ‘-l’選項用‘lib’和‘.a’把library包裹起來,而且搜索一些目錄。 |
#gcc -o main main.c –L. –lmyhello 在當前路徑下連接libmyhello.so 或者 libmyhello.a |
-L [directory] |
● 顯示指定庫搜索路徑。 ● 放在/lib和/usr/lib和/usr/local/lib裏的庫直接用-l參數就能鏈接了。但如果庫文件沒放在這三個目錄裏,而是放在其他目錄裏,這時我們只用-l參數的話,鏈接會出錯,出錯信息大概是:“/usr/bin/ld: cannot find –lxxx”,也就是鏈接程序ld在那3個目錄裏找不到libxxx.so,這時另外一個參數-L就派上用場了。 ●比如常用的X11的庫,它在/usr/X11 R6/lib目錄下,我們編譯時就要用-L/usr/X11R6/lib -lX11參數。-L參數跟着的是庫文件所在的目錄名。再比如我們把libtest.so放在/aaa/bbb/ccc目錄下,那鏈接參數就是-L/aaa/bbb/ccc –ltest。 |
#gcc -o main main.c –L. –lmyhello 在當前路徑下連接libmyhello.so 或者 libmyhello.a |
-shared |
生成一個共享目標文件,他可以和其他目標文件連接產生可執行文件。該選項指定生成動態連接庫。 |
# gcc -shared -fPCI -o libmyhello.so hello.o
|
–fPIC |
產生與位置無關的代碼並能被加載到任何地址。表示編譯爲位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的所以動態載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共享的目的。 |
# gcc -shared -fPCI -o libmyhello.so hello.o
|
2.6. 目錄選項(DIRECTORY OPTION)
選項 |
說明 |
實例 |
-I [directory] |
在頭文件的搜索路徑列表中添加directory目錄。 |
|
2.7. 調試選項(DEBUGGING OPTION)
選項 |
說明 |
實例 |
-g |
以操作系統的本地格式(stabs, COFF, XCOFF,或DWARF)產生調試信息。GDB能夠使用這些調試信息。 |
|