gcc編譯選項

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

 

 

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"。
相關文章
相關標籤/搜索