1. 程式人生 > >gcc 編譯選項

gcc 編譯選項

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

版本] -0.13  
[宣告]  
這篇文件是我的關於gcc引數的筆記,我很懷念dos年代我用小本子,紀錄任何的dos 命令的引數.哈哈,下面的東西可能也不是很全面,我參考了很多的書,和gcc的幫助.不全的原因是,有可能我還沒有看到這個引數,另一種原因是,我可能還不會用他 但是,我會慢慢的補齊的.哈哈 假如您要轉在本文章請保留我email([email protected])和文章的全面性.  
[介紹]  
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
把全域性公共符號按照大小排序後放到適當的輸出節,以防止符號間因為排布限制