您好,登錄后才能下訂單哦!
GCC參數的分別是哪些,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
大多數程序和庫在編譯時默認的優化級別是"2"(使用gcc選項:"-O2")并且在Intel/AMD平臺上默認按照i386處理器來編譯。
如果你只想讓編譯出來的程序運行在特定的平臺上,就需要執行更高級的編譯器優化選項,以產生只能運行于特定平臺的代碼。
一種方法是修改每個源碼包中的Makefile文件,在其中尋找CFLAGS和CXXFLAGS變量(C和C++編譯器的編譯選項)并修改它的值。
一些源碼包比如binutils, gcc, glibc等等,在每個子文件夾中都有Makefile文件,這樣修改起來就太累了!
另一種簡易做法是設置CFLAGS和CXXFLAGS環境變量。大多數configure腳本會使用這兩個環境變量代替Makefile文件中的值。
但是少數configure腳本并不這樣做,他們必須需要手動編輯才行。
為了設置CFLAGS和CXXFLAGS環境變量,你可以在bash中執行如下命令(也可以寫進.bashrc以成為默認值):
export CFLAGS="-O3 -march=<cpu類型>" && CXXFLAGS=$CFLAGS
這是一個確保能夠在幾乎所有平臺上都能正常工作的最小設置。
"-march"選項表示為特定的cpu類型編譯二進制代碼(不能在更低級別的cpu上運行),
Intel通常是:pentium2, pentium3, pentium3m, pentium4, pentium4m, pentium-m, prescott, nocona
說明:pentium3m/pentium4m是筆記本用的移動P3/P4;pentium-m是迅馳I/II代筆記本的cpu;
prescott是帶SSE3的P4(以滾燙到可以煎雞蛋而聞名);nocona則是最新的帶有EMT64(64位)的P4(同樣可以煎雞蛋)
AMD通常是:k6, k6-2, k6-3, athlon, athlon-tbird, athlon-xp, athlon-mp, opteron, athlon64, athlon-fx
用AMD的一般都是DIYer,就不必解釋了吧。
如果編譯時沒有抱怨"segmentation fault, core dumped",那么你設定的"-O"優化參數一般就沒什么問題。
否則請降低優化級別("-O3" -> "-O2" -> "-O1" -> 取消)。
個人意見:服務器使用"-O2"就可以了,它是最安全的優化參數(集合);桌面可以使用"-O3" ;
不鼓勵使用過多的自定義優化選項,其實他們之間沒什么明顯的速度差異(有時"-O3"反而更慢)。
編譯器對硬件非常敏感,特別是在使用較高的優化級別的時候,一丁點的內存錯誤都可能導致致命的失敗。
所以在編譯時請千萬不要超頻你的電腦(我編譯關鍵程序時總是先降頻然的)。
注意:選項的順序很重要,如果有兩個選項互相沖突,則以后一個為準。
比如"-O3"將打開-finline-functions選項,但是可以用"-O3 -fno-inline-functions"既使用-O3的功能又關閉函數內嵌功能。
更多的優化選項請參見:
http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Optimize-Options.html
http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/i386-and-x86_002d64-Options.html
http://gcc.gnu.org/onlinedocs/gcc-4.0.2/gcc/Optimize-Options.html
http://gcc.gnu.org/onlinedocs/gcc-4.0.2/gcc/i386-and-x86_002d64-Options.html
所有GCC選項完整列表參見:
http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Option-Summary.html
http://gcc.gnu.org/onlinedocs/gcc-4.0.2/gcc/Option-Summary.html
有兩個頁面值的參考:
(對于gentoo-1.4)比較安全的優化選項
http://www.freehackers.org/gentoo/gccflags/flag_gcc3.html
(對于gentoo-1.4)進階優化選項
http://www.freehackers.org/gentoo/gccflags/flag_gcc3opt.html
*******************************************************************
哦,忘了說一聲,"-O2"已經啟用絕大多數安全的優化選項了,所以其實你不必對那一堆選項發愁。
先說說"-O3"在"-O2"基礎上增加的幾項,你可以按需添加(還算比較安全):
[gcc-3.4.4]
-finline-functions 允許編譯器選擇某些簡單的函數在其被調用處展開
-fweb 為每個web結構體分配一個偽寄存器
-frename-registers 試圖驅除代碼中的假依賴關系,這個選項對具有大量寄存器的機器很有效。
[gcc-4.0.2]
-finline-functions 說明如上
-funswitch-loops 將循環體中不改變值的變量移動到循環體之外
-fgcse-after-reload **不太明白它的含義**[哪位大峽知道給小弟講解一下,先行謝過 ]
說完"-O3"再說說在嵌入式系統上常用的"-Os"選項,這個選項其實也很重要,它的含義是對生成的二進制代碼進行尺寸上的優化,它打開了所有"-O2"打開的選項,因此通常認為的"-Os"生成的二進制代碼執行效率低的潛在意識是錯誤的!當然該選項與"-O2"的不同之處在于它在"-O2"的基礎上禁止了所有為了對齊而插入的空間,也就是將所有"-falign-*"系列的選項禁用了。這種禁用究竟是否一定降低了代碼的執行效率,依據程序的不同而不同,據說某些情況下"-Os"的效率比"-O3"還要高14%!請兄弟們在實踐中自己摸索吧...
---------------------------------------------
下面選擇我認為比較重要的幾項簡單介紹一下[gcc-3.4.4],GCC選項完整列表太長了!精力有限。
[注意]這里列出的都是非默認的選項,你只需要添加你所需要的選項即可
-w 禁止輸出警告消息
-Werror 將所有警告轉換為錯誤
-Wall 顯示所有的警告消息
-v 顯示編譯程序的當前版本號
-V<version> 指定gcc將要運行的版本。只有在安裝了多個版本gcc的機器上才有效。
-ansi 按照ANSI標準編譯程序,但并不限制與標準并不沖突的GNU擴展(一般不用該選項)
-pedantic 如果要限制代碼必須嚴格符合ISO標準,就在"-ansi"的基礎上同時啟用這個選項(很少使用)
-std=<name> 指定C語言的標準(c89,c99,gnu89),該選項禁止了GNU C的擴展關鍵字asm,typeof,inline (一般不用該選項)
-static 連接器將忽略動態連接庫,同時通過將靜態目標文件直接包含到結果目標文件完成對所有引用的解析。
-shared 連接器將生成共享目標代碼,該共享庫可在運行時動態連接到程序形成完整的可執行體。
如果使用gcc命令創建共享庫作為其輸出,該選項可以防止連接器將缺失main()方法視為錯誤。
為了可以正確的工作,應該一致的使用選項"-fpic"以及目標平臺選項編譯構成同一個庫的所有共享目標模塊。
-shared-libgcc 該選項指定使用共享版本的libgcc,在沒有共享版本的libgcc的機器上該選項無效。
-specs=<filename> gcc驅動程序讀取該文件以確定哪些選項應該傳遞給那些子進程。
該選項可以通過指定配置文件來覆蓋默認配置,指定的文件將在默認配置文件讀取后進行處理以修改默認配置。
-pipe 使用管道而不是臨時文件一個階段到另一個階段交換輸出的方式,可以加快編譯速度。建議使用。
-o <filename> 指定輸出文件,對各種輸出皆有效。由于只能指定一個文件,所以在產生多個輸出文件的情況下不要使用該選項。
--help 顯示gcc的命令行選項列表;與"-v"一起使用時還將顯示gcc調用的各個進程所接受的選項。
--target-help 顯示目標機器相關的命令行選項列表
-b<machine> 指示需要編譯程序的目標機器;默認為編譯程序所運行的目標機編譯代碼。
目標機通過指定包含編譯程序的目錄來確定,通常為/usr/local/lib/gcc-lib/<machine>/<version>
-B<lib-prefix> 指定庫文件的位置,包括編譯程序的文件、執行程序和數據文件,如果需要運行子程序(如cpp,as,ld)就會用該前綴來定位。
這個前綴可以是用冒號分割的多個路徑,環境變量GCC_EXEC_PREFIX和這個選項有相同的效果。
-I<dir> 指定搜索系統頭文件的目錄,可以重復使用多個該選項指定多個目錄。
-dumpmachine 顯示該程序的目標機名字,不做其他任何動作
-dumpspecs 顯示構件編譯程序的規范信息,包括用來編譯、匯編和連接gcc編譯程序自身用到的所有選項,不做其他任何動作。
-dumpversion 顯示編譯程序自身的版本號,不做其他任何動作
-falign-functions=N 將所有函數的起始地址在N(N=1,2,4,8,16...)的邊界上對齊,默認為機器自身的默認值,指定為1表示禁止對齊。
-falign-jumps=N 將分支目標在N(N=1,2,4,8,16...)的邊界上對齊,默認為機器自身的默認值,指定為1表示禁止對齊。
-fno-align-labels 建議使用它,以保證不和-falign-jumps("-O2"默認啟用的選項)沖突
-fno-align-loops 建議使用它,以確保不會在分支目標前插入多余的空指令。
-fbranch-probabilities 在使用"-fprofile-arcs"選項編譯程序并執行它來創建包含每個代碼塊執行次數的文件之后,程序可以利用這一選項再次編譯,
文件中所產生的信息將被用來優化那些經常發生的分支代碼。如果沒有這些信息,gcc將猜測那一分支可能經常發生并進行優化。
這類優化信息將會存放在一個以源文件為名字的并以".da"為后綴的文件中。
-fno-guess-branch-probability 默認情況下gcc將使用隨機模型進行猜測哪個分支更可能被經常執行,并以此來優化代碼,該選項關閉它。
-fprofile-arcs 在使用這一選項編譯程序并運行它以創建包含每個代碼塊的執行次數的文件后,程序可以再次使用"-fbranch-probabilities"編譯,
文件中的信息可以用來優化那些經常選取的分支。如果沒有這些信息,gcc將猜測哪個分支將被經常運行以進行優化。
這類優化信息將會存放在一個以源文件為名字的并以".da"為后綴的文件中。
-fforce-addr 必須將地址復制到寄存器中才能對他們進行運算。由于所需地址通常在前面已經加載到寄存器中了,所以這個選項可以改進代碼。
-fforce-mem 必須將數值復制到寄存器中才能對他們進行運算。由于所需數值通常在前面已經加載到寄存器中了,所以這個選項可以改進代碼。
-ffreestanding 所編譯的程序能夠在獨立的環境中運行,該環境可以沒有標準庫,而且可以不從main()函數開始運行。
該選項將設置"-fno-builtin",且等同于"-fno-hosted"。
-fhosted 所編譯的程序需要運行在宿主環境中,其中需要有完整的標準庫,而且main()函數具有int型的返回值。
-fno-builtin 除非利用"__builtin_"進行引用,否則不識別所有內建函數。
-fmerge-all-constants 試圖將跨編譯單元的所有常量值和數組合并在一個副本中。但是標準C/C++要求每個變量都必須有不同的存儲位置。
-fmove-all-movables 將所有不變的表達式移動到循環體之外,這種做法的好壞取決于源代碼中的循環結構。
-fnon-call-exceptions 產生的代碼可供陷阱指令(如非法浮點運算和非法內存尋址)拋出異常,需要相關平臺的運行時支持,并不普遍有效。
-fomit-frame-pointer 對于不需要棧指針的函數就不在寄存器中保存指針,因此可以忽略存儲和檢索地址的代碼,并將寄存器用于普通用途。
所有"-O"級別都打開著一選項,但僅在調試器可以不依靠棧指針運行時才有效。建議不需要調試的情況下顯式的設置它。
-fno-optional-diags 禁止輸出診斷消息,C++標準并不需要這些消息。
-fpermissive 將代碼中與標準不符合的診斷消息作為警告而不是錯誤輸出。
-fpic 生成可用于共享庫的位置獨立代碼(PIC),所有的內存尋址均通過全局偏移表(GOT)完成。該選項并非在所有的機器上都有效。
要確定一個地址,需要將代碼自身的內存位置作為表中的一項插入。該選項可以產生在共享庫中存放并從中加載的目標模塊。
-fprefetch-loop-arrays 生成數組預讀取指令,對于使用巨大數組的程序可以加快代碼執行速度,適合數據庫相關的大型軟件等。
-freg-struct-return 生成用寄存器返回短結構的代碼,如果寄存器無法榮納將使用內存。
-fstack-check 為防止程序棧溢出而進行必要的檢測,在多線程環境中運行時才可能需要它。
-ftime-report 編譯完成后顯示編譯耗時的統計信息
-funroll-loops 如果在編譯時可以確定迭代的次數非常少而且循環中的指令也非常少,可以使用該選項進行循環展開,以驅除循環和復制指令。
-finline-limit=<size> 對偽指令數超過<size>的函數,編譯程序將不進行展開,默認為600
--param <name>=<value> gcc內部存在一些優化代碼程度的限制,調整這些限制就是調整整個優化全局。下面列出了參數的名字和對應的解釋:
名字 解釋
max-delay-slot-insn-search 較大的數目可以生成更優化的代碼,但是會降低編譯速度,默認為100
max-delay-slot-live-search 較大的數目可以生成更優化的代碼,但是會降低編譯速度,默認為333
max-gcse-memory 執行GCSE優化使用的最大內存量,太小將使該優化無法進行,默認為50M
max-gcse-passes 執行GCSE優化的最大迭代次數,默認為1
*******************************************************************
說完了命令行選項,下面來說說與硬件體系結構(主要是cpu)相關的設置[僅針對i386/x86_64]
最大名鼎鼎的"-march"上面已經說過了,下面講講別的(僅挑些實用的)
-mfpmath=sse P3和athlon-tbird以上級別的cpu支持
-masm=<dialect> 使用指定的dialect輸出匯編語言指令,可以使用"intel"或"att";默認為"att"
-mieee-fp 指定編譯器使用IEEE浮點比較,這樣將會正確的處理比較結果為無序的情況。
-malign-double 將double, long double, long long對齊于雙字節邊界上;有助于生成更高速的代碼,但是程序的尺寸會變大。
-m128bit-long-double 指定long double為128位,pentium以上的cpu更喜歡這種標準。
-mregparm=N 指定用于傳遞整數參數的寄存器數目(默認不使用寄存器)。0<=N<=3 ;注意:當N>0時你必須使用同一參數重新構建所有的模塊,包括所有的庫。
-mmmx
-mno-mmx
-msse
-mno-sse
-msse2
-mno-sse2
-msse3
-mno-sse3
-m3dnow
-mno-3dnow
上面的這些不用解釋了,一看就明白,根據自己的CPU決定吧
-maccumulate-outgoing-args 指定在函數引導段中計算輸出參數所需最大空間,這在大部分現代cpu中是較快的方法;缺點是會增加代碼尺寸。
-mthreads 支持Mingw32的線程安全異常處理。對于依賴于線程安全異常處理的程序,必須啟用這個選項。
使用這個選項時會定義"-D_MT",它將包含使用選項"-lmingwthrd"連接的一個特殊的線程輔助庫,用于為每個線程清理異常處理數據。
-minline-all-stringops 嵌入所有的字符串操作。可以提高字符串操作的性能,但是會增加代碼尺寸。
-momit-leaf-frame-pointer 不為葉子函數在寄存器中保存棧指針,這樣可以節省寄存器,但是將會是調試變的困難。參見"-fomit-frame-pointer"。
下面這幾個僅用于x86_64環境:
-m64 生成專門運行于64位環境的代碼,不能運行于32位環境
-mcmodel=small [默認值]程序和它的符號必須位于2GB以下的地址空間。指針仍然是64位。程序可以靜態連接也可以動態連接。
-mcmodel=kernel 內核運行于2GB地址空間之外。在編譯linux內核時必須使用該選項!
-mcmodel=medium 程序必須位于2GB以下的地址空間,但是它的符號可以位于任何地址空間。程序可以靜態連接也可以動態連接。
注意:共享庫不能使用這個選項編譯!
-mcmodel=large 對地址空間沒有任何限制,這個選項的功能目前尚未實現。
==============================
既然已經講了這么多了索性再講講gcc使用的一些環境變量
除了大名鼎鼎的CFLAGS和CXXFLAGS以外(其實是Autoconf的環境變量),再挑幾個說說:
所有的PATH類環境變量(除LD_RUN_PATH外)都是用冒號分割的目錄列表。
C_INCLUDE_PATH 編譯C程序時使用的環境變量,用于查找頭文件。
CPLUS_INCLUDE_PATH 編譯C++程序時使用的環境變量,用于查找頭文件。
OBJC_INCLUDE_PATH 編譯Obj-C程序時使用的環境變量,用于查找頭文件。
CPATH 編譯C/C++/Obj-C程序時使用的環境變量,用于查找頭文件。
COMPILER_PATH 如果沒有用GCC_EXEC_PREFIX定位子程序,編譯程序將會在此查找它的子程序。
LIBRARY_PATH 連接程序將在這些目錄中尋找特殊的連接程序文件。
LD_LIBRARY_PATH 該環境變量不影響編譯程序,但是程序運行的時候會有影響:程序會查找該目錄列表以尋找共享庫。
當不能夠在編譯程序的目錄中找到共享庫的時候,執行程序必須設置該環境變量。
LD_RUN_PATH 該環境變量不影響編譯程序,但是程序運行的時候會有影響:它在運行時指出了文件的名字,運行的程序可以由此得到它的符號名字和地址。
由于地址不會重新載入,因而可能符號應用其他文件中的絕對地址。這個和ld工具使用的"-R"選項完全一樣。
GCC_EXEC_PREFIX 編譯程序執行所有子程序的名字的前綴,默認值是"<prefix>/lib/gcc-lib/",
其中的<prefix>是安裝時configure腳本指定的前綴。
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"
TMPDIR 編譯程序存放臨時工作文件的臨時目錄,這些臨時文件通常在編譯結束時被刪除。
看完上述內容,你們掌握GCC參數的分別是哪些的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。