gcc編譯器1.gcc編譯流程及編譯選項分析1-1.預處理階段1-2.編譯階段1-3.匯編階段1-4.鏈接階段2.gcc編譯選項分析2-1.總體選項2-2.警告和出錯選項2-3:優化信息2-4:體系結構相關選項3.拓展
GCC(GNU Compiler Collection,GNU編譯器套裝)是一套由GNU開發的編程語言編譯器。它是一套以GPL及LPGL許可證所發行的自由軟件,也是GNU計划的關鍵部分,亦是自由的類UNIX及蘋果電腦MAC Os X操作系統的標准編譯器。GCC原名為GNU C語言編譯器(GNU C Compiler),因為它原本只能處理C語言。GCC很快的擴展,變得可處理C++。之后可處理Fortrna、Pascal、Objecttive-c、java、Ada,以及Go與其他語言。GCC是一個交叉平台平台編譯,能夠在當前GPU平台上為多種不同體系結構的硬件平台開發軟件,因此適合在嵌入式領域的開發編譯。
以下是gcc支持編譯的一些源文件的后綴及其解釋:
-
.c,C語言源代碼;
-
.h,程序所包含的頭文件;
-
.i,已經預處理過的C源代碼文件;
-
.s,匯編語言源代碼文件;
-
.o,編譯后的目標文件;
1.gcc編譯流程及編譯選項分析
gcc編譯流程分成4個步驟,分別為:
- 預處理(Pre-Processing);
- 編譯(Compiling);
- 匯編(Assembing);
- 鏈接(Linking);
源碼:
Make文件:
.PHONY:all clean
CC = gcc
all:
$(CC) -E hello.c -o hello.i
$(CC) -S hello.i -o hello.s
$(CC) -c hello.s -o hello.o
$(CC) hello.o -o hello
clean:
rm -rf *.i *.s *.o hello
1-1.預處理階段
在該階段,編譯器將上述代碼中的stdio.h編譯進來,並且用戶可以使用gcc的選項“-E”進行查看。該選項的作用是讓gcc在預處理結束后停止編譯過程。
1-2.編譯階段
接下來進行的是編譯階段。在這個階段中,gcc首先檢查代碼的規范性、是否有語法錯誤等,以確定代碼的實際要做的工作。在檢查無誤后,gcc把代碼翻譯成匯編語言。
用戶可以使用“-S”選項來進行查看,該選項只進行編譯而不進行匯編,生成匯編代碼。
1-3.匯編階段
匯編階段是把編譯階段生成的“.s”文件轉成目標文件。
1-4.鏈接階段
在成功編譯后,就進入了鏈接階段。這里涉及一個重要的概念:函數庫。關於實現“printf”函數,在沒有特別指定時,gcc會到系統默認的搜索路徑“/usr/lib”下進行查找,從而鏈接到libc.so.6庫函數,這樣就實現函數printf。這就是鏈接的作用。
函數庫一般分為靜態庫和動態庫。
靜態庫:是指在編譯鏈接時,把庫文件的代碼全部加入到可執行文件中,因此生成的文件較大,但在運行時也就不在需要庫文件,其后綴名一般為“.a”。
動態庫:在編譯鏈接時並沒有把庫文件的代碼加入到可執行文件中,而是在程序執行時由運行時鏈接文件加載庫,這樣可以節省系統的開銷。動態庫一般后綴名為“.so”。
gcc默認在編譯時是哦那個動態庫,完成鏈接后,gcc就可以生成可執行文件。
[fly@fly-vm hello]$ make
gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o
gcc hello.o -o hello
[fly@fly-vm hello]$ ./hello
Hello, wolrd.
2.gcc編譯選項分析
gcc有超過100個的可用選項,主要包括總體選項、警告和出錯選項、優化選項和體系結構相關選項。以下對每一類中最常用的選項分別進行講解。
2-1.總體選項
gcc [選項] 文件
-E:使用此選項表示僅作預處理,不進行編譯、匯編和鏈接。
-S:編譯到匯編語言不進行匯編和鏈接。
-c:編譯到目標代碼。
-o:文件輸出到文件。
-static:禁止使用動態庫。
-share:盡量使用動態庫。
-I dir:在頭文件的搜索路徑列表中添加dir目錄。
-L dir:在庫文件的搜索路徑列表中添加dir目錄。
-llibrary:鏈接名為library的庫文件。
2-2.警告和出錯選項
警告是針對程序結構的診斷信息,出現警告程序不一定有錯誤,而是表明有風險,或者可能存在錯誤。
-Wall:打開所有類型的語法警告。
-Wcomment:當"/"出現在“/......*/”注釋中,或者“\”出現在“//...”注釋結尾處時,給出警告。
-fsyntax-only:檢查程序中的語法錯誤,但是不產生輸出信息。
-w:禁止所有警告信息。
-Wno-import:禁止所有關於#import的警告信息。
-ansi:強制gcc生成標准語法所要求的告警信息。
-pedantic:打開完全服從ANSI C標准所需的全部警告診斷;拒絕接收采用了被禁止的語法擴展程序。
-predantic-errors:和-pedantic類似,但是顯示錯誤而不是信息。
-g:生成調試信息。GNU調試器(GDB)可以利用該信息。
2-3:優化信息
-O0:無優化(默認)。
-O和-O1:使用能減少目標文件大小及執行時間並且不會使編譯時間明顯增加的優化。在編譯大型程序的時候會顯著增加編譯時內存的使用。
-O2:包含-O1的優化並增加了不需要在目標文件大小和執行速度上進行折衷的優化。編譯器不執行循環展開以及內聯函數。此選項將增加編譯時間和目標文件的執行性能。
-Os:專門優化目標文件大小,執行所有的不增加目標文件大小的-O2優化選項,並且執行專門減少目標文件大小的優化選項。
-O3:打開所有-O2的優化選項並且增加-finline-functions、-funswitch-loops、-fpredictive-commoning、-fgcse-after-reload和-free-vectorize優化目標。
Tips:
雖然優化選項可以加速代碼的運行速度,但對於調試而言將是一個很大的挑戰。因為代碼在經過優化后,原先在程序中聲明和使用的變量很可能不再使用,控制流可能會突然跳轉到意外的地方,循環語句也有可能因為循環展開而變得到處都有,這些對調試來講都是一場噩夢。
因此,在調試的時候最好不要使用任何優化選項,只有當程序在最終發行的時候才考慮對其進行優化。
2-4:體系結構相關選項
-mcpu=type:針對不同CPU使用相應的CPU指令。type可選:i386、i486、pentium(i686)。
-mieee-fp:使用IEEE標准進行浮點數的比較。
-mno-ieee-fp:不使用IEEE標准進行浮點數的比較。
-msoft-float:輸出包含浮點庫調用的目標代碼。
-mshort:把int類型作為16位處理,相當於short int。
-mrtd:強行將函數參數個數固定的函數用ret NUM返回,這樣可以節省一條調用指令。
3.拓展
https://gitee.com/c-program/mark-down-doc/blob/master/1-LinuxSys/gcc%20compiler.md