gcc選項


摘自http://blog.csdn.net/liuchao1986105/article/details/6674822

版本] -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] 

[參數詳解]  
-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文檔 

-S  
  只激活預處理和編譯,就是指把文檔編譯成為匯編代碼。  
  例子用法  
  gcc -S hello.c  
  他將生成.s的匯編代碼,您能夠用文本編輯器察看 

-E  
  只激活預處理,這個不生成文檔,您需要把他重定向到一個輸出文檔里面.  
  例子用法:  
  gcc -E hello.c > pianoapan.txt  
  gcc -E hello.c | more  
  慢慢看吧,一個hello word 也要和處理成800行的代碼 

-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 

-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語言特性 

 

 

gcc提供了大量的警告選項,對代碼中可能存在的問題提出警 告,通常可以使用-Wall來開啟以下警告:
           -Waddress -Warray-bounds (only with -O2) -Wc++0x-compat
           -Wchar-subscripts -Wimplicit-int -Wimplicit-function-declaration
           -Wcomment -Wformat -Wmain (only for C/ObjC and unless
           -ffreestanding) -Wmissing-braces -Wnonnull -Wparentheses
           -Wpointer-sign -Wreorder -Wreturn-type -Wsequence-point
           -Wsign-compare (only in C++) -Wstrict-aliasing -Wstrict-overflow=1
           -Wswitch -Wtrigraphs -Wuninitialized (only with -O1 and above)
           -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value
           -Wunused-variable
unused-function:警告聲明但是沒有定義的static函數;
unused- label:聲明但是未使用的標簽;
unused-parameter:警告未使用的函數參數;
unused-variable:聲明但 是未使用的本地變量;
unused-value:計算了但是未使用的值;
format:printf和scanf這樣的函數中的格式字符 串的使用不當;
implicit-int:未指定類型;
implicit-function:函數在聲明前使用;
char- subscripts:使用char類作為數組下標(因為char可能是有符號數);
missingbraces:大括號不匹配;
parentheses: 圓括號不匹配;
return-type:函數有無返回值以及返回值類型不匹配;
sequence-point:違反順序點的代碼,比如 a[i] = c[i++];
switch:switch語句缺少default或者switch使用枚舉變量為索引時缺少某個變量的case;
strict- aliasing=n:使用n設置對指針變量指向的對象類型產生警告的限制程度,默認n=3;只有在-fstrict-aliasing設置的情況下有 效;
unknow-pragmas:使用未知的#pragma指令;
uninitialized:使用的變量為初始化,只在-O2時有 效;

以下是在-Wall中不會激活的警告選項:
cast-align:當指針進行類型轉換后有內存對齊要求更嚴格時發出警告;
sign- compare:當使用signed和unsigned類型比較時;
missing-prototypes:當函數在使用前沒有函數原型時;
packed:packed 是gcc的一個擴展,是使結構體各成員之間不留內存對齊所需的 空 間,有時候會造成內存對齊的問題;
padded:也是gcc的擴展,使結構體成員之間進行內存對齊的填充,會 造成結構體體積增大.
unreachable-code:有不會執行的代碼時.
inline:當inline函數不再保持inline時 (比如對inline函數取地址);
disable-optimization:當不能執行指定的優化時.(需要太多時間或 系統資源).
可以使用 -Werror時所有的警告都變成錯誤,使出現警告時也停止編譯.需要和指定警告的參數一起使用.

優化:
gcc默認提供了5級優 化選項的集合:
-O0:無優化(默認)
-O和-O1:使用能減少目標 文 件大小以及執行時間並且不會使編譯時間明顯增加的優化.在編譯大型程序的時候會顯著增加編譯時內存的使用.
-O2: 包含-O1的優化並增加了不需要在目標文件大小和執行速度上進行折衷的優化.編譯器不執行循環展開以及函數內聯.此選項將增加編譯時間和目標文件的執行性 能.
-Os:專門優化目標文件大小,執行所有的不增加目標文件大小的-O2優化選項.並且執行專門減小目標文件大小的優化選項.
-O3: 打開所有-O2的優化選項並且增加 -finline-functions, -funswitch-loops,-fpredictive-commoning, -fgcse-after-reload and -ftree-vectorize優化選項.

-O1包含的選項-O1通常可以安全的和調試的選項一起使用:
           -fauto-inc-dec -fcprop-registers -fdce -fdefer-pop -fdelayed-branch
           -fdse -fguess-branch-probability -fif-conversion2 -fif-conversion
           -finline-small-functions -fipa-pure-const -fipa-reference
           -fmerge-constants -fsplit-wide-types -ftree-ccp -ftree-ch
           -ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse
           -ftree-fre -ftree-sra -ftree-ter -funit-at-a-time

以下所有的優化選項需要在名字 前加上-f,如果不需要此選項可以使用-fno-前綴
defer-pop:延遲到只在必要時從函數參數棧中pop參數;
thread- jumps:使用跳轉線程優化,避免跳轉到另一個跳轉;
branch-probabilities:分支優化;
cprop- registers:使用寄存器之間copy-propagation傳值;
guess-branch-probability:分支預測;
omit- frame-pointer:可能的情況下不產生棧幀;

-O2:以下是-O2在-O1基礎上增加的優化選項:
           -falign-functions  -falign-jumps -falign-loops  -falign-labels
           -fcaller-saves -fcrossjumping -fcse-follow-jumps  -fcse-skip-blocks
           -fdelete-null-pointer-checks -fexpensive-optimizations -fgcse
           -fgcse-lm -foptimize-sibling-calls -fpeephole2 -fregmove
           -freorder-blocks  -freorder-functions -frerun-cse-after-loop
           -fsched-interblock  -fsched-spec -fschedule-insns
           -fschedule-insns2 -fstrict-aliasing -fstrict-overflow -ftree-pre
           -ftree-vrp
cpu架構的優化選項,通常是-mcpu(將被取消);-march,-mtune

Debug選項:
在 gcc編譯源代碼時指定-g選項可以產生帶有調試信息的目標代碼,gcc可以為多個不同平台上帝不同調試器提供調試信息,默認gcc產生的調試信息是為 gdb使用的,可以使用-gformat 指定要生成的調試信息的格式以提供給其他平台的其他調試器使用.常用的格式有
-ggdb:生成gdb專 用的調試信息,使用最適合的格式(DWARF 2,stabs等)會有一些gdb專用的擴展,可能造成其他調試器無法運行.
-gstabs:使用 stabs格式,不包含gdb擴展,stabs常用於BSD系統的DBX調試器.
-gcoff:產生COFF格式的調試信息,常用於System V下的SDB調試器;
-gxcoff:產生XCOFF格式的調試信息,用於IBM的RS/6000下的DBX調試器;
-gdwarf- 2:產生DWARF version2 的格式的調試信息,常用於IRIXX6上的DBX調試器.GCC會使用DWARF version3的一些特性.
可 以指定調試信息的等級:在指定的調試格式后面加上等級:
如: -ggdb2 等,0代表不產生調試信息.在使用-gdwarf-2時因為最早的格式為-gdwarf2會造成混亂,所以要額外使用一個-glevel來指定調試信息的 等級,其他格式選項也可以另外指定等級.

gcc可以使用-p選項指定生成信息以供porf使用.

 

GCC常用選項

選項 含義
--help 
--target-help
顯示 gcc 幫助說明。‘target-help’是顯示目標機器特定的命令行選項。
--version 顯示 gcc 版本號和版權信息 。
-ooutfile 輸出到指定的文件。
-xlanguage 指明使用的編程語言。允許的語言包括:c c++ assembler none 。 ‘none’意味着恢復默認行為,即根據文件的擴展名猜測源文件的語言。
-v 打印較多信息,顯示編譯器調用的程序。
-### 與 -v 類似,但選項被引號括住,並且不執行命令。
-E 僅作預處理,不進行編譯、匯編和鏈接。如上圖所示。
-S 僅編譯到匯編語言,不進行匯編和鏈接。如上圖所示。
-c 編譯、匯編到目標代碼,不進行鏈接。如上圖所示。
-pipe 使用管道代替臨時文件。
-combine 將多個源文件一次性傳遞給匯編器。

 

 

3 其他GCC選項

更多有用的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 文件,真是一件很累人的事!

CC 與 CXX

這是 C 與 C++ 編譯器命令。默認值一般是 "gcc" 與 "g++"。這個變量本來與優化沒有關系,但是有些人因為擔心軟件包不遵守那些約定俗成的規范,害怕自己苦心設置的 CFLAGS/CXXFLAGS/LDFLAGS 之類的變量被忽略了,而索性將原本應當放置在其它變量中的選項一股老兒塞到 CC 或 CXX 中,比如:CC="gcc -march=k8 -O2 -s"。這是一種怪異的用法,本文不提倡這種做法,而是提倡按照變量本來的含義使用變量。

CPPFLAGS

這是用於預處理階段的選項。不過能夠用於此變量的選項,看不出有哪個與優化相關。如果你實在想設一個,那就使用下面這兩個吧:

-DNDEBUG
"NDEBUG"是一個標准的 ANSI 宏,表示不進行調試編譯。
-D_FILE_OFFSET_BITS=64
大多數包使用這個來提供大文件(>2G)支持。

CFLAGS 與 CXXFLAGS

CFLAGS 表示用於 C 編譯器的選項,CXXFLAGS 表示用於 C++ 編譯器的選項。這兩個變量實際上涵蓋了編譯和匯編兩個步驟。大多數程序和庫在編譯時默認的優化級別是"2"(使用"-O2"選項)並且帶有調試符號來編 譯,也就是 CFLAGS="-O2 -g", CXXFLAGS=$CFLAGS 。事實上,"-O2"已經啟用絕大多數安全的優化選項了。另一方面,由於大部分選項可以同時用於這兩個變量,所以僅在最后講述只能用於其中一個變量的選 項。[提醒]下面所列選項皆為非默認選項,你只要按需添加即可。

先說說"-O3"在"-O2"基礎上增加的幾項:

-finline-functions
允許編譯器選擇某些簡單的函數在其被調用處展開,比較安全的選項,特別是在CPU二級緩 存較大時建議使用。
-funswitch-loops
將循環體中不改變值的變量移動到循環體之外。
-fgcse-after-reload
為了清除多余的溢出,在重載之后執行一個額外的載入消除步驟。

另外:

-fomit-frame-pointer
對於不需要棧指針的函數就不在寄存器中保存指針,因此可以忽略存儲和檢索地址的代 碼,同時對許多函數提供一個額外的寄存器。所有"-O"級別都打開它,但僅在調試器可以不依靠棧指針運行時才有效。在AMD64平台上此選項默認打開,但 是在x86平台上則默認關閉。建議顯式的設置它。
-falign-functions=N
-falign-jumps=N
-falign-loops=N
-falign-labels=N
這 四個對齊選項在"-O2"中打開,其中的根據不同的平台N使用不同的默認值。如果你想指定不同於默認值的N,也可以單獨指定。比如,對於L2- cache>=1M的cpu而言,指定 -falign-functions=64 可能會獲得更好的性能。建議在指定了 -march 的時候不明確指定這里的值。

調試選項:

-fprofile-arcs
在使用這一選項編譯程序並運行它以創建包含每個代碼塊的執行次數的文件后,程序可以再次使用 -fbranch-probabilities 編譯,文件中的信息可以用來優化那些經常選取的分支。如果沒有這些信息,gcc將猜測哪個分支將被經常運行以進行優化。這類優化信息將會存放在一個以源文 件為名字的並以".da"為后綴的文件中。

全局選項:

-pipe
在編譯過程的不同階段之間使用管道而非臨時文件進行通信,可以加快編譯速度。建議使用。

目錄選項:

--sysroot=dir
將dir作為邏輯根目錄。比如編譯器通常會在 /usr/include 和 /usr/lib 中搜索頭文件和庫,使用這個選項后將在 dir/usr/include 和 dir/usr/lib 目錄中搜索。如果使用這個選項的同時又使用了 -isysroot 選項,則此選項僅作用於庫文件的搜索路徑,而 -isysroot 選項將作用於頭文件的搜索路徑。這個選項與優化無關,但是在 CLFS 中有着神奇的作用。

代碼生成選項:

-fno-bounds-check
關閉所有對數組訪問的邊界檢查。該選項將提高數組索引的性能,但當超出數組邊界時,可能會 造成不可接受的行為。
-freg-struct-return
如果struct和union足夠小就通過寄存器返回,這將提高較小結構的效率。如果 不夠小,無法容納在一個寄存器中,將使用內存返回。建議僅在完全使用GCC編譯的系統上才使用。
-fpic
生成可用於共享庫的位置獨立代碼。所有的內部尋址均通過全局偏移表完成。要確定一個地址,需要將代碼自身的內存位置 作為表中一項插入。該選項產生可以在共享庫中存放並從中加載的目標模塊。
-fstack-check
為防止程序棧溢出而進行必要的檢測,僅在多線程環境中運行時才可能需要它。
-fvisibility=hidden
設置默認的ELF鏡像中符號的可見性為隱藏。使用這個特性可以非常充分的提高連接和加 載共享庫的性能,生成更加優化的代碼,提供近乎完美的API輸出和防止符號碰撞。我們強烈建議你在編譯任何共享庫的時候使用該選項。參見 -fvisibility-inlines-hidden 選項。

硬件體系結構相關選項[僅僅針對x86與x86_64]:

-march=cpu-type
為特定的cpu-type編譯二進制代碼(不能在更低級別的cpu上運行)。Intel可以 用:pentium2, pentium3(=pentium3m), pentium4(=pentium4m), pentium-m, prescott, nocona, core2(GCC-4.3新增) 。AMD可以用:k6-2(=k6-3), athlon(=athlon-tbird), athlon-xp(=athlon-mp), k8(=opteron=athlon64=athlon-fx)
-mfpmath=sse
P3和athlon-xp級別及以上的cpu支持"sse"標量浮點指令。僅建議在P4和K8以上級 別的處理器上使用該選項。
-malign-double
將double, long double, long long對齊於雙字節邊界上;有助於生成更高速的代碼,但是程序的尺寸會變大,並且不能與未使用該選項編譯的程序一起工作。
-m128bit-long-double
指定long double為128位,pentium以上的cpu更喜歡這種標准,並且符合x86-64的ABI標准,但是卻不附合i386的ABI標准。
-mregparm=N
指定用於傳遞整數參數的寄存器數目(默認不使用寄存器)。0<=N<=3 ;注意:當N>0時你必須使用同一參數重新構建所有的模塊,包括所有的庫。
-msseregparm
使用SSE寄存器傳遞float和double參數和返回值。注意:當你使用了這個選項以后,你必須 使用同一參數重新構建所有的模塊,包括所有的庫。
-mmmx
-msse
-msse2
-msse3
-m3dnow
-mssse3(沒寫錯!GCC-4.3 新增)
-msse4.1(GCC-4.3新增)
-msse4.2(GCC-4.3新增)
-msse4(含4.1和 4.2,GCC-4.3新增)
是否使用相應的擴展指令集以及內置函數,按照自己的cpu選擇吧!
-maccumulate-outgoing-args
指定在函數引導段中計算輸出參數所需最大空間,這在大部分現代cpu中 是較快的方法;缺點是會明顯增加二進制文件尺寸。
-mthreads
支持Mingw32的線程安全異常處理。對於依賴於線程安全異常處理的程序,必須啟用這個選項。使用這個選 項時會定義"-D_MT",它將包含使用選項"-lmingwthrd"連接的一個特殊的線程輔助庫,用於為每個線程清理異常處理數據。
-minline-all-stringops
默認時GCC只將確定目的地會被對齊在至少4字節邊界的字符串操作內聯進程序代 碼。該選項啟用更多的內聯並且增加二進制文件的體積,但是可以提升依賴於高速 memcpy, strlen, memset 操作的程序的性能。
-minline-stringops-dynamically
GCC-4.3新增。對未知尺寸字符串的小塊操作使用內聯代 碼,而對大塊操作仍然調用庫函數,這是比"-minline-all-stringops"更聰明的策略。決定策略的算法可以通 過"-mstringop-strategy"控制。
-momit-leaf-frame-pointer
不為葉子函數在寄存器中保存棧指針,這樣可以節省寄存器,但是將會使調試 變的困難。注意:不要與 -fomit-frame-pointer 同時使用,因為會造成代碼效率低下。
-m64
生成專門運行於64位環境的代碼,不能運行於32位環境,僅用於x86_64[含EMT64]環境。
-mcmodel=small
[默認值]程序和它的符號必須位於2GB以下的地址空間。指針仍然是64位。程序可以靜態連接也 可以動態連接。僅用於x86_64[含EMT64]環境。
-mcmodel=kernel
內核運行於2GB地址空間之外。在編譯linux內核時必須使用該選項!僅用於 x86_64[含EMT64]環境。
-mcmodel=medium
程序必須位於2GB以下的地址空間,但是它的符號可以位於任何地址空間。程序可以靜態連接也可 以動態連接。注意:共享庫不能使用這個選項編譯!僅用於x86_64[含EMT64]環境。

其它優化選項:

-fforce-addr
必須將地址復制到寄存器中才能對他們進行運算。由於所需地址通常在前面已經加載到寄存器中了,所以這 個選項可以改進代碼。
-finline-limit=n
對偽指令數超過n的函數,編譯程序將不進行內聯展開,默認為600。增大此值將增加編譯時間 和編譯內存用量並且生成的二進制文件體積也會變大,此值不宜太大。
-fmerge-all-constants
試圖將跨編譯單元的所有常量值和數組合並在一個副本中。但是標准C/C++要求每 個變量都必須有不同的存儲位置,所以該選項可能會導致某些不兼容的行為。
-fgcse-sm
在全局公共子表達式消除之后運行存儲移動,以試圖將存儲移出循環。gcc-3.4中曾屬於"-O2"級別的 選項。
-fgcse-las
在全局公共子表達式消除之后消除多余的在存儲到同一存儲區域之后的加載操作。gcc-3.4中曾屬 於"-O2"級別的選項。
-floop-optimize
已廢除(GCC-4.1曾包含在"-O1"中)。
-floop-optimize2
使用改進版本的循環優化器代替原來"-floop-optimize"。該優化器將使用不同 的選項(-funroll-loops, -fpeel-loops, -funswitch-loops, -ftree-loop-im)分別控制循環優化的不同方面。目前這個新版本的優化器尚在開發中,並且生成的代碼質量並不比以前的版本高。已廢除,僅存在 於GCC-4.1之前的版本中。
-funsafe-loop-optimizations
假定循環不會溢出,並且循環的退出條件不是無窮。這將可以在一個比較 廣的范圍內進行循環優化,即使優化器自己也不能斷定這樣做是否正確。
-fsched-spec-load
允許一些裝載指令執行一些投機性的動作。
-ftree-loop-linear
在trees上進行線型循環轉換。它能夠改進緩沖性能並且允許進行更進一步的循環優化。
-fivopts
在trees上執行歸納變量優化。
-ftree-vectorize
在trees上執行循環向量化。
-ftracer
執行尾部復制以擴大超級塊的尺寸,它簡化了函數控制流,從而允許其它的優化措施做的更好。據說挺有效。
-funroll-loops
僅對循環次數能夠在編譯時或運行時確定的循環進行展開,生成的代碼尺寸將變大,執行速度可能變快 也可能變慢。
-fprefetch-loop-arrays
生成數組預讀取指令,對於使用巨大數組的程序可以加快代碼執行速度,適合數據庫 相關的大型軟件等。具體效果如何取決於代碼。
-fweb
建立經常使用的緩存器網絡,提供更佳的緩存器使用率。gcc-3.4中曾屬於"-O3"級別的選項。
-ffast-math
違反IEEE/ANSI標准以提高浮點數計算速度,是個危險的選項,僅在編譯不需要嚴格遵守IEEE規 范且浮點計算密集的程序考慮采用。
-fsingle-precision-constant
將浮點常量作為單精度常量對待,而不是隱式地將其轉換為雙精度。
-fbranch-probabilities
在使用 -fprofile-arcs 選項編譯程序並執行它來創建包含每個代碼塊執行次數的文件之后,程序可以利用這一選項再次編譯,文件中所產生的信息將被用來優化那些經常發生的分支代碼。 如果沒有這些信息,gcc將猜測那一分支可能經常發生並進行優化。這類優化信息將會存放在一個以源文件為名字的並以".da"為后綴的文件中。
-frename-registers
試圖驅除代碼中的假依賴關系,這個選項對具有大量寄存器的機器很有效。gcc-3.4中 曾屬於"-O3"級別的選項。
-fbranch-target-load-optimize
-fbranch-target-load-optimize2
在 執行序啟動以及結尾之前執行分支目標緩存器加載最佳化。
-fstack-protector
在關鍵函數的堆棧中設置保護值。在返回地址和返回值之前,都將驗證這個保護值。如果出現了 緩沖區溢出,保護值不再匹配,程序就會退出。程序每次運行,保護值都是隨機的,因此不會被遠程猜出。
-fstack-protector-all
同上,但是在所有函數的堆棧中設置保護值。
--param max-gcse-memory=xxM
執行GCSE優化使用的最大內存量(xxM),太小將使該優化無法進 行,默認為50M。
--param max-gcse-passes=n
執行GCSE優化的最大迭代次數,默認為 1。

傳遞給匯編器的選項:

-Wa,options
options是一個或多個由逗號分隔的可以傳遞給匯編器的選項列表。其中的每一個均可作為命令行選項 傳遞給匯編器。
-Wa,--strip-local-absolute
從輸出符號表中移除局部絕對符號。
-Wa,-R
合並數據段和正文段,因為不必在數據段和代碼段之間轉移,所以它可能會產生更短的地址移動。
-Wa,--64
設置字長為64bit,僅用於x86_64,並且僅對ELF格式的目標文件有效。此外,還需要使 用"--enable-64-bit-bfd"選項編譯的BFD支持。
-Wa,-march=CPU
按照特定的CPU進行優化:pentiumiii, pentium4, prescott, nocona, core, core2; athlon, sledgehammer, opteron, k8 。

僅可用於 CFLAGS 的選項:

-fhosted
按宿主環境編譯,其中需要有完整的標准庫,入口必須是main()函數且具有int型的返回值。內核以外幾乎 所有的程序都是如此。該選項隱含設置了 -fbuiltin,且與 -fno-freestanding 等價。
-ffreestanding
按獨立環境編譯,該環境可以沒有標准庫,且對main()函數沒有要求。最典型的例子就是操作系 統內核。該選項隱含設置了 -fno-builtin,且與 -fno-hosted 等價。

僅可用於 CXXFLAGS 的選項:

-fno-enforce-eh-specs
C++標准要求強制檢查異常違例,但是該選項可以關閉違例檢查,從而減小生成代碼 的體積。該選項類似於定義了"NDEBUG"宏。
-fno-rtti
如果沒有使用'dynamic_cast'和'typeid',可以使用這個選項禁止為包含虛方法的類生成 運行時表示代碼,從而節約空間。此選項對於異常處理無效(仍然按需生成rtti代碼)。
-ftemplate-depth-n
將最大模版實例化深度設為'n',符合標准的程序不能超過17,默認值為500。
-fno-optional-diags
禁止輸出診斷消息,C++標准並不需要這些消息。
-fno-threadsafe-statics
GCC自動在訪問C++局部靜態變量的代碼上加鎖,以保證線程安全。如果你不 需要線程安全,可以使用這個選項。
-fvisibility-inlines-hidden
默認隱藏所有內聯函數,從而減小導出符號表的大小,既能縮減文件的大 小,還能提高運行性能,我們強烈建議你在編譯任何共享庫的時候使用該選項。參見 -fvisibility=hidden 選項。

LDFLAGS

LDFLAGS 是傳遞給連接器的選項。這是一個常被忽視的變量,事實上它對優化的影響也是很明顯的。

[提示]以下選項是在完整的閱讀了ld-2.18文檔之后挑選出來的選項。 http://blog.chinaunix.net/u1/41220/showart_354602.html 有2.14版本的中文手冊。

-s
刪除可執行程序中的所有符號表和所有重定位信息。其結果與運行命令 strip 所達到的效果相同,這個選項是比較安全的。
-Wl,options
options是由一個或多個逗號分隔的傳遞給鏈接器的選項列表。其中的每一個選項均會作為命令行選項 提供給鏈接器。
-Wl,-On
當n>0時將會優化輸出,但是會明顯增加連接操作的時間,這個選項是比較安全的。
-Wl,--exclude-libs=ALL
不自動導出庫中的符號,也就是默認將庫中的符號隱藏。
-Wl,-m<emulation>
仿真<emulation>連接器,當前ld所有可用的仿真可以 通過"ld -V"命令獲取。默認值取決於ld的編譯時配置。
-Wl,--sort-common
把全局公共符號按照大小排序后放到適當的輸出節,以防止符號間因為排布限制而出現間隙。
-Wl,-x
刪除所有的本地符號。
-Wl,-X
刪除所有的臨時本地符號。對於大多數目標平台,就是所有的名字以'L'開頭的本地符號。
-Wl,-zcomberloc
組合多個重定位節並重新排布它們,以便讓動態符號可以被緩存。
-Wl,--enable-new-dtags
在ELF中創建新式的"dynamic tags",但在老式的ELF系統上無法識別。
-Wl,--as-needed
移除不必要的符號引用,僅在實際需要的時候才連接,可以生成更高效的代碼。
-Wl,--no-define-common
限制對普通符號的地址分配。該選項允許那些從共享庫中引用的普通符號只在主程序 中被分配地址。這會消除在共享庫中的無用的副本的空間,同時也防止了在有多個指定了搜索路徑的動態模塊在進行運行時符號解析時引起的混亂。
-Wl,--hash-style=gnu
使用gnu風格的符號散列表格式。它的動態鏈接性能比傳統的sysv風格(默認)有 較大提升,但是它生成的可執行程序和庫與舊的Glibc以及動態鏈接器不兼容。

最后說兩個與優化無關的系統環境變量,因為會影響GCC編譯程序的方式,下面兩個是咱中國人比較關心的:

LANG
指定編譯程序使用的字符集,可用於創建寬字符文件、串文字、注釋;默認為英文。[目前只支持日文"C-JIS,C- SJIS,C-EUCJP",不支持中文]
LC_ALL
指定多字節字符的字符分類,主要用於確定字符串的字符邊界以及編譯程序使用何種語言發出診斷消息;默認設置與 LANG相同。中文相關的幾項:"zh_CN.GB2312 , zh_CN.GB18030 , zh_CN.GBK , zh_CN.UTF-8 , zh_TW.BIG5"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM