摘自http://blog.csdn.net/liuchao1986105/article/details/6674822html
版本] -0.13
[聲明]
這篇文檔是個人關於gcc參數的筆記,我很懷念dos年代我用小本子,紀錄任何的dos 命令的參數.哈哈,下面的東西可能也不是很全面,我參考了不少的書,和gcc的幫助.不全的緣由是,有可能我尚未看到這個參數,另外一種緣由是,我可能還不會用他 可是,我會慢慢的補齊的.哈哈 假如您要轉在本文章請保留我email(pianopan@beeship.com)和文章的全面性.
[介紹]
gcc and g++分別是gnu的c & c++編譯器 gcc/g++在執行編譯工做的時候,總共須要4步
1.預處理,生成.i的文檔[預處理器cpp]
2.將預處理後的文檔不轉換成彙編語言,生成文檔.s[編譯器egcs]
3.有彙編變爲目標代碼(機器代碼)生成.o的文檔[彙編器as]
4.鏈接目標代碼,生成可執行程式[連接器ld] linux
[參數詳解]
-x language filename
設定文檔所使用的語言,使後綴名無效,對之後的多個有效.也就是根據約定C語言的後綴名稱是.c的,而C++的後綴名是.C或.cpp,假如您很個性,決定您的C代碼文檔的後綴名是.pig 哈哈,那您就要用這個參數,這個參數對他後面的文檔名都起做用,除非到了下一個參數的使用。
可以使用的參數嗎有下面的這些
`c', `objective-c', `c-header', `c++', `cpp-output', `assembler', and `assembler-with-cpp'.
看到英文,應該可以理解的。
例子用法:
gcc -x c hello.pig
-x none filename
關掉上一個選項,也就是讓gcc根據文檔名後綴,自動識別文檔類型
例子用法:
gcc -x c hello.pig -x none hello2.c
-c
只激活預處理,編譯,和彙編,也就是他只把程式作成obj文檔
例子用法:
gcc -c hello.c
他將生成.o的obj文檔 c++
-S
只激活預處理和編譯,就是指把文檔編譯成爲彙編代碼。
例子用法
gcc -S hello.c
他將生成.s的彙編代碼,您可以用文本編輯器察看 web
-E
只激活預處理,這個不生成文檔,您須要把他重定向到一個輸出文檔裏面.
例子用法:
gcc -E hello.c > pianoapan.txt
gcc -E hello.c | more
慢慢看吧,一個hello word 也要和處理成800行的代碼 objective-c
-o
定製目標名稱,缺省的時候,gcc 編譯出來的文檔是a.out,很難聽,假如您和我有同感,改掉他,哈哈
例子用法
gcc -o hello.exe hello.c (哦,windows用習慣了)
gcc -o hello.asm -S hello.c 算法
-pipe
使用管道代替編譯中臨時文檔,在使用非gnu彙編工具的時候,可能有些問題
gcc -pipe -o hello.exe hello.c 數據庫
-ansi
關閉gnu c中和ansi c不兼容的特性,激活ansi c的專有特性(包括禁止一些asm inline typeof關鍵字,連同UNIX,vax等預處理宏, 編程
-fno-asm
此選項實現ansi選項的功能的一部分,他禁止將asm,inline和typeof用做關鍵字。
-fno-strict-prototype
只對g++起做用,使用這個選項,g++將對不帶參數的函數,都認爲是沒有顯式的對參數的個數和類型說明,而不是沒有參數.
而gcc不管是否使用這個參數,都將對沒有帶參數的函數,認爲城沒有顯式說明的類型
-fthis-is-varialble
就是向傳統c++看齊,可以使用this當通常變量使用.
-fcond-mismatch
容許條件表達式的第二和第三參數類型不匹配,表達式的值將爲void類型
-funsigned-char
-fno-signed-char
-fsigned-char
-fno-unsigned-char
這四個參數是對char類型進行配置,決定將char類型配置成unsigned char(前兩個參數)或 signed char(後兩個參數)
-include file
包含某個代碼,簡單來講,就是便以某個文檔,須要另外一個文檔的時候,就可以用他設定,功能就至關於在代碼中使用#include<filename>
例子用法:
gcc hello.c -include /root/pianopan.h
-imacros file
將file文檔的宏,擴展到gcc/g++的輸入文檔,宏定義自己並不出如今輸入文檔中
-Dmacro
至關於C語言中的#define macro
-Dmacro=defn
至關於C語言中的#define macro=defn
-Umacro
至關於C語言中的#undef macro windows
-undef
取消對任何非標準宏的定義
-Idir
在您是用#include"file"的時候,gcc/g++會先在當前目錄查找您所定製的頭文檔,假如沒有找到,他回到缺省的頭文檔目錄找,假如使用-I定製了目錄,他
回先在您所定製的目錄查找,而後再按常規的順序去找.
對於#include<file>,gcc/g++會到-I定製的目錄查找,查很難找到,而後將到系統的缺省的頭文檔目錄查找
-I-
就是取消前一個參數的功能,因此通常在-Idir以後使用
-idirafter dir
在-I的目錄裏面查找失敗,講到這個目錄裏面查找.
-iprefix prefix
-iwithprefix dir
通常一塊兒使用,當-I的目錄查找失敗,會到prefix+dir下查找
-nostdinc
使編譯器再也不繫統缺省的頭文檔目錄裏面找頭文檔,通常和-I聯合使用,明確限定頭文檔的位置
-nostdin C++
規定不在g++指定的標準路經中搜索,但仍在其餘路徑中搜索,.此選項在創libg++庫使用
-C
在預處理的時候,不刪除註釋信息,通常和-E使用,有時候分析程式,用這個很方便的
-M
生成文檔關聯的信息。包含目標文檔所依賴的任何源代碼您可以用gcc -M hello.c來測試一下,很簡單。
-MM
和上面的那個相同,可是他將忽略由#include<file>形成的依賴關係。
-MD
和-M相同,可是輸出將導入到.d的文檔裏面
-MMD
和-MM相同,可是輸出將導入到.d的文檔裏面
-Wa,option
此選項傳遞option給彙編程式;假如option中間有逗號,就將option分紅多個選項,而後傳遞給會彙編程式
-Wl.option
此選項傳遞option給鏈接程式;假如option中間有逗號,就將option分紅多個選項,而後傳遞給會鏈接程式.
數組
-llibrary
定製編譯的時候使用的庫
例子用法
gcc -lcurses hello.c
使用ncurses庫編譯程式
-Ldir
定製編譯的時候,搜索庫的路徑。好比您本身的庫,可以用他定製目錄,否則
編譯器將只在標準庫的目錄找。這個dir就是目錄的名稱。
-O0
-O1
-O2
-O3
編譯器的優化選項的4個級別,-O0表示沒有優化,-O1爲缺省值,-O3優化級別最高
-g
只是編譯器,在編譯的時候,產生調試信息。
-gstabs
此選項以stabs格式聲稱調試信息,可是不包括gdb調試信息.
-gstabs+
此選項以stabs格式聲稱調試信息,而且包含僅供gdb使用的額外調試信息.
-ggdb
此選項將盡量的生成gdb的可以使用的調試信息.
-static
此選項將禁止使用動態庫,因此,編譯出來的東西,通常都很大,也無需什麼
動態鏈接庫,就可以運行.
-share
此選項將盡可能使用動態庫,因此生成文檔比較小,可是須要系統由動態庫.
-traditional
試圖讓編譯器支持傳統的C語言特性
|
選項 | 含義 |
---|---|
--help --target-help |
顯示 gcc 幫助說明。‘target-help’是顯示目標機器特定的命令行選項。 |
--version | 顯示 gcc 版本號和版權信息 。 |
-ooutfile | 輸出到指定的文件。 |
-xlanguage | 指明使用的編程語言。容許的語言包括:c c++ assembler none 。 ‘none’意味着恢復默認行爲,即根據文件的擴展名猜想源文件的語言。 |
-v | 打印較多信息,顯示編譯器調用的程序。 |
-### | 與 -v 相似,但選項被引號括住,而且不執行命令。 |
-E | 僅做預處理,不進行編譯、彙編和連接。如上圖所示。 |
-S | 僅編譯到彙編語言,不進行彙編和連接。如上圖所示。 |
-c | 編譯、彙編到目標代碼,不進行連接。如上圖所示。 |
-pipe | 使用管道代替臨時文件。 |
-combine | 將多個源文件一次性傳遞給彙編器。 |
更多有用的GCC選項:
命令 | 描述 |
---|---|
-l library -llibrary |
進行連接時搜索名爲library的庫。 例子: $ gcc test.c -lm -o test |
-Idir | 把dir加入到搜索頭文件的路徑列表中。 例子: $ gcc test.c -I../inc -o test |
-Ldir | 把dir加入到搜索庫文件的路徑列表中。 例子: $ gcc -I/home/foo -L/home/foo -ltest test.c -o test |
-Dname | 預約義一個名爲name的宏,值爲1。 例子: $ gcc -DTEST_CONFIG test.c -o test |
-Dname=definition | 預約義名爲name,值爲definition的宏。 |
-ggdb -ggdblevel |
爲調試器 gdb 生成調試信息。level能夠爲1,2,3,默認值爲2。 |
-g -glevel |
生成操做系統本地格式的調試信息。-g 和 -ggdb 並不太相同, -g 會生成 gdb 以外的信息。level取值同上。 |
-s | 去除可執行文件中的符號表和重定位信息。用於減少可執行文件的大小。 |
-M | 告訴預處理器輸出一個適合make的規則,用於描述各目標文件的依賴關係。對於每一個 源文件,預處理器輸出 一個make規則,該規則的目標項(target)是源文件對應的目標文件名,依賴項(dependency)是源文件中 `#include引用的全部文件。生成的規則可 以是單行,但若是太長,就用`\'-換行符續成多行。規則 顯示在標準輸出,不產生預處理過的C程序。 |
-C | 告訴預處理器不要丟棄註釋。配合`-E'選項使用。 |
-P | 告訴預處理器不要產生`#line'命令。配合`-E'選項使用。 |
-static | 在支持動態連接的系統上,阻止鏈接共享庫。該選項在其它系統上 無效。 |
-nostdlib | 不鏈接系統標準啓動文件和標準庫文件,只把指定的文件傳遞給鏈接器。 |
Warnings | |
-Wall | 會打開一些頗有用的警告選項,建議編譯時加此選項。 |
-W -Wextra |
打印一些額外的警告信息。 |
-w | 禁止顯示全部警告信息。 |
-Wshadow | 當一個局部變量遮蓋住了另外一個局部變量,或者全局變量時,給出警告。頗有用的選項,建議打開。 -Wall 並不會打開此項。 |
-Wpointer-arith | 對函數指針或者void *類型的指針進行算術操做時給出警告。也頗有用。 -Wall 並不會打開此項。 |
-Wcast-qual | 當強制轉化丟掉了類型修飾符時給出警告。 -Wall 並不會打開此項。 |
-Waggregate-return | 若是定義或調用了返回結構體或聯合體的函數,編譯器就發出警告。 |
-Winline | 不管是聲明爲 inline 或者是指定了-finline-functions 選項,若是某函數不能內聯,編譯器都將發出警告。若是你的代碼含有不少 inline 函數的話,這是頗有用的選項。 |
-Werror | 把警告看成錯誤。出現任何警告就放棄編譯。 |
-Wunreachable-code | 若是編譯器探測到永遠不會執行到的代碼,就給出警告。也是比較有用的選項。 |
-Wcast-align | 一旦某個指針類型強制轉換致使目標所需的地址對齊增長時,編譯器就發出警告。 |
-Wundef | 當一個沒有定義的符號出如今 #if 中時,給出警告。 |
-Wredundant-decls | 若是在同一個可見域內某定義屢次聲明,編譯器就發出警告,即便這些重複聲明有效而且毫無差異。 |
Optimization | |
-O0 | 禁止編譯器進行優化。默認爲此項。 |
-O -O1 |
嘗試優化編譯時間和可執行文件大小。 |
-O2 | 更多的優化,會嘗試幾乎所有的優化功能,但不會進行「空間換時間」的優化方法。 |
-O3 | 在 -O2 的基礎上再打開一些優化選項:-finline-functions, -funswitch-loops 和 -fgcse-after-reload 。 |
-Os | 對生成文件大小進行優化。它會打開 -O2 開的所有選項,除了會那些增長文件大小的。 |
-finline-functions | 把全部簡單的函數內聯進調用者。編譯器會探索式地決定哪些函數足夠簡單,值得作這種內聯。 |
-fstrict-aliasing | 施加最強的別名規則(aliasing rules)。 |
Standard | |
-ansi | 支持符合ANSI標準的C程序。這樣就會關閉GNU C中某些不兼容ANSI C的特性。 |
-std=c89 -iso9899:1990 |
指明使用標準 ISO C90 做爲標準來編譯程序。 |
-std=c99 -std=iso9899:1999 |
指明使用標準 ISO C99 做爲標準來編譯程序。 |
-std=c++98 | 指明使用標準 C++98 做爲標準來編譯程序。 |
-std=gnu9x -std=gnu99 |
使用 ISO C99 再加上 GNU 的一些擴展。 |
-fno-asm | 不把asm, inline或typeof看成關鍵字,所以這些詞能夠用作標識符。用 __asm__, __inline__和__typeof__可以替代它們。 `-ansi' 隱含聲明瞭`-fno-asm'。 |
-fgnu89-inline | 告訴編譯器在 C99 模式下看到 inline 函數時使用傳統的 GNU 句法。 |
C options | |
-fsigned-char -funsigned-char |
把char定義爲有/無符號類型,如同signed char/unsigned char。 |
-traditional | 嘗試支持傳統C編譯器的某些方面。詳見GNU C手冊。 |
-fno-builtin -fno-builtin-function |
不接受沒有 __builtin_ 前綴的函數做爲內建函數。 |
-trigraphs | 支持ANSI C的三聯符( trigraphs)。`-ansi'選項隱含聲明瞭此選項。 |
-fsigned-bitfields -funsigned-bitfields |
若是沒有明確聲明`signed'或`unsigned'修飾符,這些選項用來定義有符號位域或無符號位域。缺省狀況下,位域是有符號的,由於它們繼承的基本整數類型,如int,是有符號數。 |
-Wstrict-prototypes | 若是函數的聲明或定義沒有指出參數類型,編譯器就發出警告。頗有用的警告。 |
-Wmissing-prototypes | 若是沒有預先聲明就定義了全局函數,編譯器就發出警告。即便函數定義自身提供了函數原形也會產生這個警告。這個選項 的目的是檢查沒有在頭文件中聲明的全局函數。 |
-Wnested-externs | 若是某extern聲明出如今函數內部,編譯器就發出警告。 |
C++ options | |
-ffor-scope | 從頭開始執行程序,也容許進行重定向。 |
-fno-rtti | 關閉對 dynamic_cast 和 typeid 的支持。若是你不須要這些功能,關閉它會節省一些空間。 |
-Wctor-dtor-privacy | 當一個類沒有用時給出警告。由於構造函數和析構函數會被看成私有的。 |
-Wnon-virtual-dtor | 當一個類有多態性,而又沒有虛析構函數時,發出警告。-Wall會開啓這個選項。 |
-Wreorder | 若是代碼中的成員變量的初始化順序和它們實際執行時初始化順序不一致,給出警告。 |
-Wno-deprecated | 使用過期的特性時不要給出警告。 |
-Woverloaded-virtual | 若是函數的聲明隱藏住了基類的虛函數,就給出警告。 |
Machine Dependent Options (Intel) | |
-mtune=cpu-type | 爲指定類型的 CPU 生成代碼。cpu-type能夠是:i386,i486,i586,pentium,i686,pentium4 等等。 |
-msse -msse2 -mmmx -mno-sse -mno-sse2 -mno-mmx |
使用或者不使用MMX,SSE,SSE2指令。 |
-m32 -m64 |
生成32位/64位機器上的代碼。 |
-mpush-args -mno-push-args |
(不)使用 push 指令來進行存儲參數。默認是使用。 |
-mregparm=num | 當傳遞整數參數時,控制所使用寄存器的個數。 |
讓咱們先看看 Makefile 規則中的編譯命令一般是怎麼寫的。
大多數軟件包遵照以下約定俗成的規範:
#1,首先從源代碼生成目標文件(預處理,編譯,彙編),"-c"選項表示不執行連接步驟。 $(CC) $(CPPFLAGS) $(CFLAGS) example.c -c -o example.o #2,而後將目標文件鏈接爲最終的結果(鏈接),"-o"選項用於指定輸出文件的名字。 $(CC) $(LDFLAGS) example.o -o example #有一些軟件包一次完成四個步驟: $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) example.c -o example
固然也有少數軟件包不遵照這些約定俗成的規範,好比:
#1,有些在命令行中漏掉應有的Makefile變量(注意:有些遺漏是故意的) $(CC) $(CFLAGS) example.c -c -o example.o $(CC) $(CPPFLAGS) example.c -c -o example.o $(CC) example.o -o example $(CC) example.c -o example #2,有些在命令行中增長了沒必要要的Makefile變量 $(CC) $(CFLAGS) $(LDFLAGS) example.o -o example $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) example.c -c -o example.o
固然還有極個別軟件包徹底是"胡來":亂用變量(增長沒必要要的又漏掉了應有的)者有之,不用$(CC)者有之,不一而足.....
儘管將源代碼編譯爲二進制文件的四個步驟由不一樣的程序(cpp,gcc/g++,as,ld)完成,可是事實上 cpp, as, ld 都是由 gcc/g++ 進行間接調用的。換句話說,控制了 gcc/g++ 就等於控制了全部四個步驟。從 Makefile 規則中的編譯命令能夠看出,編譯工具的行爲全靠 CC/CXX CPPFLAGS CFLAGS/CXXFLAGS LDFLAGS 這幾個變量在控制。固然理論上控制編譯工具行爲的還應當有 AS ASFLAGS ARFLAGS 等變量,可是實踐中基本上沒有軟件包使用它們。
那麼咱們如何控制這些變量呢?一種簡易的作法是首先設置與這些 Makefile 變量同名的環境變量並將它們 export 爲全局,而後運行 configure 腳本,大多數 configure 腳本會使用這同名的環境變量代替 Makefile 中的值。可是少數 configure 腳本並不這樣作(好比GCC-3.4.6和Binutils-2.16.1的腳本就不傳遞LDFLAGS),你必須手動編輯生成的 Makefile 文件,在其中尋找這些變量並修改它們的值,許多源碼包在每一個子文件夾中都有 Makefile 文件,真是一件很累人的事!
這是 C 與 C++ 編譯器命令。默認值通常是 "gcc" 與 "g++"。這個變量原本與優化沒有關係,可是有些人由於擔憂軟件包不遵照那些約定俗成的規範,懼怕本身苦心設置的 CFLAGS/CXXFLAGS/LDFLAGS 之類的變量被忽略了,而索性將本來應當放置在其它變量中的選項一股老兒塞到 CC 或 CXX 中,好比:CC="gcc -march=k8 -O2 -s"。這是一種怪異的用法,本文不提倡這種作法,而是提倡按照變量原本的含義使用變量。
這是用於預處理階段的選項。不過可以用於此變量的選項,看不出有哪一個與優化相關。若是你實在想設一個,那就使用下面這兩個吧:
CFLAGS 表示用於 C 編譯器的選項,CXXFLAGS 表示用於 C++ 編譯器的選項。這兩個變量實際上涵蓋了編譯和彙編兩個步驟。大多數程序和庫在編譯時默認的優化級別是"2"(使用"-O2"選項)而且帶有調試符號來編 譯,也就是 CFLAGS="-O2 -g", CXXFLAGS=$CFLAGS 。事實上,"-O2"已經啓用絕大多數安全的優化選項了。另外一方面,因爲大部分選項能夠同時用於這兩個變量,因此僅在最後講述只能用於其中一個變量的選 項。[提醒]下面所列選項皆爲非默認選項,你只要按需添加便可。
先說說"-O3"在"-O2"基礎上增長的幾項:
另外:
調試選項:
全局選項:
目錄選項:
代碼生成選項:
硬件體系結構相關選項[僅僅針對x86與x86_64]:
其它優化選項:
傳遞給彙編器的選項:
僅可用於 CFLAGS 的選項:
僅可用於 CXXFLAGS 的選項:
LDFLAGS 是傳遞給鏈接器的選項。這是一個常被忽視的變量,事實上它對優化的影響也是很明顯的。
[提示]如下選項是在完整的閱讀了ld-2.18文檔以後挑選出來的選項。 http://blog.chinaunix.net/u1/41220/showart_354602.html 有2.14版本的中文手冊。
最後說兩個與優化無關的系統環境變量,由於會影響GCC編譯程序的方式,下面兩個是咱中國人比較關心的: