轉自:html
http://www.jinbuguo.com/linux/optimize_guide.htmllinux
GCC 編譯優化指南
版權聲明
本文做者是一位開源理念的堅決支持者,因此本文雖然不是軟件,可是遵守開源的精神發佈。web
- 無擔保:本文做者不保證做品內容準確無誤,亦不承擔任何因爲使用此文檔所致使的損失。
- 自由使用:任何人均可以自由的閱讀/連接/打印此文檔,無需任何附加條件。
- 名譽權:任何人均可以自由的轉載/引用/再創做此文檔,但必須保留做者署名並註明出處。
其餘做品
本文做者十分願意與他人分享勞動成果,若是你對個人其餘翻譯做品或者技術文章有興趣,能夠在以下位置查看現有的做品集:算法
聯繫方式
因爲做者水平有限,所以不能保證做品內容準確無誤。若是你發現了做品中的錯誤,請您來信指出,哪怕是錯別字也好,任何提升做品質量的建議我都將虛心接納。數據庫
前言
網上關於編譯優化的文章不少,但大多零零散散,不成體系,本文試圖給出一個完整和清晰的優化思路,同時提供在實踐中如何進行優化的詳盡參考。可是, 在介紹全部優化知識以前首先引用LFS-Book中的一句忠告:「使用編譯器優化獲得的小幅度性能提高,與它帶來的風險相比微不足道」。你還要進行優化 嗎?數組
%@&#=^%~*# ...
OK, crazy guy! Let's Go!!緩存
在繼續以前,做者仍是奉勸各位:若是追求極致的優化,那麼它將是一件既耗時又麻煩的事情,你會陷入無止盡的測試、測試、再測試……另外 Gentoo wiki 上有這麼一句話:"GCC has well over a hundred individual optimization flags and it would be insane to try and describe them all."因此本文不會涉及所有GCC優化選項。最後做者仍是再羅唆一句:優化應當適可而止爲好,將精力留出來作一些其它事情會更有意義!安全
先決條件
本文的主要讀者是 LFS/Gentoo 的玩家,基本上比較 crazy 的玩家都接觸過,若是你以前從未使用過 LFS/Gentoo ,請先按照《Linux From Scratch 6.2 中文版》作一遍 LFS ,而後再來閱讀此文將會更有意義。另外,本文是創建在《深刻理解軟件包的配置、編譯與安裝》一文基礎之上的,在開始閱讀本文以前,請先閱讀它。網絡
基本原理
咱們首先從三個方面來看與優化相關的內容:多線程
- 從運行時的依賴關係來看,對性能有較大影響的組件有 kernel 和 glibc ,雖然這嚴格說來這不屬於本文的話題,可是通過精心選擇、精心配置、精心編譯的內核與C庫將對提升系統的運行速度起着基礎性的做用。
- 從被編譯的軟件包來看,每一個軟件包的 configure 腳本都提供了許多配置選項,其中有許多選項是與性能息息相關的。好比,對於 Apache-2.2.6 而言,你可使用 --enable-MODULE=static 將模塊靜態編譯進核心,使用 --disable-MODULE 禁用不須要的模塊,使用 --with-mpm=MPM 選擇一個高效的多路處理模塊,在不須要IPv6的狀況下使用 --disable-ipv6 禁用IPv6支持,在不使用線程化的MPM時使用 --disable-threads 禁用線程支持,等等……這部份內容顯然不可能在本文中進行完整的講述,本文只能講述與優化相關的通用選項。針對特定的軟件包,請在編譯前使用 configure --help 查看全部選項,並精心選擇。
- 從編譯過程自身來看,將源代碼編譯爲二進制文件是在 Makefile 文件的指導下,由 make 程序調用一條條編譯命令完成的。而將源代碼編譯爲二進制文件又須要通過如下四個步驟:預處理(cpp) → 編譯(gcc或g++) → 彙編(as) → 鏈接(ld) ;括號中表示每一個階段所使用的程序,它們分別屬於 GCC 和 Binutils 軟件包。顯然的,優化應當從編譯工具自身的選擇以及控制編譯工具的行爲入手。
大致上編譯優化就這"三板斧"(實際上是"三腳貓")了,本文接下來的內容將討論這隻貓的後兩隻腳。
編譯工具的選擇
對於編譯工具自身的選擇,在假定使用 Binutils 和 GCC 以及 Make 的前提下,沒什麼好說的,基本上新版本都能帶來性能提高,同時比老版本對新硬件的支持更好,因此應當儘可能選用新版本。不過追新也可能帶來系統的不穩定,這 就要針對實際狀況進行權衡了。本文以 Binutils-2.18 和 GCC-4.2.2/GCC-4.3.0 以及 Make-3.81 爲例進行說明。
configure 選項
這裏咱們只講解通用的"體系結構選項",因爲"特性選項"在每一個軟件包之間千差萬別,因此不可能在此處進行講解。
這部份內容很簡單,而且其含義也是不言而喻的,下面只列出經常使用的值:
- i586-pc-linux-gnu
- i686-pc-linux-gnu
- x86_64-pc-linux-gnu
- powerpc-unknown-linux-gnu
- powerpc64-unknown-linux-gnu
若是你實在不知道應當使用哪個,那麼就乾脆不使用這幾個選項,讓 config.guess 腳本本身去猜吧,反正也挺準的。
編譯選項
讓咱們先看看 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 是傳遞給鏈接器的選項。這是一個常被忽視的變量,事實上它對優化的影響也是很明顯的。
-
-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"。