gcc筆記

GCC 最初的意思是GNU C Compiler,而後變成了 GNU Compiler Collection,也就是 GNU 編譯器家族(常見的語言都支持)。


內容如下:
1. GCC的組成部分以及使用到的軟件
2. 編譯和鏈接
3. gcc選項
4. 庫搜索路徑


1,GCC的組成部分以及使用到的軟件
GCC 是由許多組件組成的。表 1 列出了 GCC 的各個部分,但它們也並不總是出現 的。有些部分是和語言相關的,所以如果沒有安裝某種特定語言,系統中就不會出現相關的文件。

表1:GCC 安裝的各個部分
部分 描述
c++ gcc 的一個版木,默認語言設置爲 C++,而且在連接的時候自動包含標準 C++ 庫。這和 g++ 一樣
ccl 實際的C編譯程序
cclplus 實際的 C++ 編澤程序
collect2 在不使用 GNU 連接程序的系統上,有必要運行 collect2 來產生特定的全局初始化代碼(例如 C++ 的構造函數和析構函數)
configure GCC 源代碼樹根目錄中的一個腳木。用於設置配置值和創建GCC 編譯程序必需的 make 程序的描述文件
crt0.o 這個初始化和結束代碼是爲每個系統定製的,而且也被編譯進該文件,該文件然後會被連接到每個可執行文件中來執行必要的啓動和終止程序
cygwin1.dll Windows 的共享庫提供的 API,模擬 UNIX 系統調用
f77 該驅動程序可用於編譯 Fortran
f771 實際的 Fortran 編譯程序
g++ gcc 的一個版木,默認語言設置爲 C++,而且在連接的時候自動包含標準 C++ 庫。這和 c++ 一樣
gcc 該驅動程序等同於執行編譯程序和連接程序以產生需要的輸出
gcj 該驅動程序用於編譯 Java
gnat1 實際的 Ada 編譯程序
gnatbind 一種工具,用於執行 Ada 語言綁定
gnatlink 一種工具,用於執行 Ada 語言連接
jc1 實際的 Java 編譯程序
libgcc 該庫包含的例程被作爲編澤程序的一部分,是因爲它們可被連接到實際的可執行程序中。 它們是特殊的例程,連接到可執行程序,來執行基木的任務,例如浮點運算。這些庫中的例程通常都是平臺相關的
libgcj 運行時庫包含所有的核心 Java 類
libobjc 對所有 Objective-C 程序都必須的運行時庫
libstdc++ 運行時庫,包括定義爲標準語言一部分的所有的 C++ 類和函數


表 2 列出的軟件和 GCC 協同工作,目的是實現編譯過程。有些是很基本的(例如 as 和 Id),而其他一些則是非常有用但不是嚴格需耍的。儘管這些工具中的很多都是各種 UNIX 系統的本地共具,但還是能夠通過 GNU 包 binutils 得到大多數工具。
 

表2:GCC 使用的軟件工具
工具 描述
addr2line 給出一個可執行文件的內部地址,addr2line 使用文件中的調試信息將地址翻澤成源代碼文 件名和行號。該程序是 binutils 包的一部分
ar 這是一個程序,可通過從文檔中增加、刪除和析取文件來維護庫文件。通常使用該工具是爲了創建和管理連接程序使用的目標庫文檔。該程序是 binutils 包的一部分
as GNU 彙編器。實際上它是一族彙編器,因爲它可以被編澤或能夠在各種不同平臺上工作。 該程序是 binutils 包的一部分
autoconf 產生的 shell 腳木自動配置源代碼包去編澤某個特定版木的 UNIX
c++filt 程序接受被 C++ 編澤程序轉換過的名字(不是被重載的),而且將該名字翻澤成初始形式。 該程序是 binutils 包的一部分
f2c 是 Fortran 到C的翻譯程序。不是 GCC 的一部分
gcov gprof 使用的配置工具,用來確定程序運行的時候哪一部分耗時最大
gdb GNU 調試器,可用於檢查程序運行時的值和行爲
GNATS GNU 的調試跟蹤系統(GNU Bug Tracking System)。一個跟蹤 GCC 和其他 GNU 軟件問題的在線系統
gprof 該程序會監督編澤程序的執行過程,並報告程序中各個函數的運行時間,可以根據所提供 的配置文件來優化程序。該程序是 binutils 包的一部分
ld GNU 連接程序。該程序將目標文件的集合組合成可執行程序。該程序是 binutils 包的一部
libtool 一個基本庫,支持 make 程序的描述文件使用的簡化共享庫用法的腳木
make 一個工具程序,它會讀 makefile 腳木來確定程序中的哪個部分需要編澤和連接,然後發佈 必要的命令。它讀出的腳木(叫做 makefile 或 Makefile)定義了文件關係和依賴關係
nlmconv 將可重定位的目標文件轉換成 NetWare 可加載模塊(NetWare Loadable Module, NLM)。該 程序是 binutils 的一部分
nm 列出目標文件中定義的符號。該程序是 binutils 包的一部分
objcopy 將目標文件從一種二進制格式複製和翻譯到另外一種。該程序是 binutils 包的一部分
objdump 顯示一個或多個目標文件中保存的多種不同信息。該程序是 binutils 包的一部分
ranlib 創建和添加到 ar 文檔的索引。該索引被 Id 使用來定位庫中的模塊。該程序是 binutils 包的一部分
ratfor Ratfor 預處理程序可由 GCC 激活,但不是標準 GCC 發佈版的一部分
readelf 從 ELF 格式的目標文件顯示信息。該程序是 binutils 包的一部分
size 列出目標文件中每個部分的名字和尺寸。該程序是 binutils 包的一部分
strings 瀏覽所有類型的文件,析取出用於顯示的字符串。該程序是 binutils 包的一部分
strip 從目標文件或文檔庫中去掉符號表,以及其他調試所需的信息。該程序是 binutils 包的一部
vcg Ratfor 瀏覽器從文木文件中讀取信息,並以圖表形式顯示它們。而 vcg 工具並不是 GCC 發佈中的一部分,但 -dv 選項可被用來產生 vcg 可以理解的優化數據的格式
windres Window 資源文件編澤程序。該程序是 binutils 包的一部分

2,編譯和鏈接
1)編譯和鏈接一次性操作完成
方法1:gcc main.c  #在 gcc 命令後面緊跟源文件名,會在當前目錄生成a.out可執行文件

方法2:gcc main.c -o main #可以透過-o指定生成exe文件的名稱

2)編譯和鏈接分開操作
step1:編譯
方法1: gcc -c main.c #就將 main.c 編譯爲 main.o

方法2:gcc -c main.c -o a.o #這樣生成的目標文件的名字就是 a.o

step2:鏈接
方法1:gcc main.o #就將 main.o 鏈接爲 a.out

方法2:gcc main.o -o main.out #這樣生成的可執行文件的名字就是 main.out

3,GCC 編譯器在編譯一個C語言程序時需要經過以下 4 步:
將C語言源程序預處理,生成.i文件。
預處理後的.i文件編譯成爲彙編語言,生成.s文件。
將彙編語言文件經過彙編,生成目標文件.o文件。
將各個模塊的.o文件鏈接起來生成一個可執行程序文件。

GCC 編譯流程如下圖所示:

GCCç¼è¯æµç¨

.i文件、.s文件、.o文件可以認爲是中間文件或臨時文件,如果使用 GCC 一次性完成C語言程序的編譯,那麼只能看到最終的可執行文件,這些中間文件都是看不到的,因爲 GCC 已經經它們刪除了。

3,gcc選項

-c
編譯、彙編指定的源文件,但是不進行鏈接

-S
將C語言源文件編譯爲彙編語言,但是並不彙編該程序。使用該選項,我們可以查看C語言代碼對應的彙編代碼。

-E
將C語言源文件進行預處理,但是並不編譯該程序。對於一般的預處理問題,可以使用這個選項進行查看,例如,宏的展開問題、文件的包含問題等。

-I
指定包含的頭文件的目錄

-g 選項
可生成能被 gdb 調試器所使用的調試信息。

-o
指定輸出文件

-o [file1] [file2]    
將文件 file2 編譯成可執行文件 file1

+++++++++++++++++++++++++++++++++++++++++++++++++++
-o選項使用舉例
1) 將源文件作爲輸入文件,將可執行文件作爲輸出文件,也即完整地編譯整個程序:
$ gcc main.c func.c -o app.out

將 main.c 和 func.c 兩個源文件編譯成一個可執行文件,其名字爲 app.out。如果不使用 -o 選項,那麼將生成名字爲 a.out 的可執行文件。

2) 將源文件作爲輸入文件,將目標文件作爲輸出文件,也即只編譯不鏈接:
$ gcc -c main.c -o a.o

將源文件 main.c 編譯爲目標文件 a.o。如果不使用 -o 選項,那麼將生成名爲 main.o 的目標文件。

3) 將源文件作爲輸入文件,將預處理文件作爲輸出文件,也即只進行預處理操作:
$ gcc -E main.c -o demo.i

對源文件 main.c 進行預處理操作,並將結果放在 demo.i 文件中。如果不使用 -o 選項,那麼將生成名爲 main.i 的預處理文件。

4) 將目標文件作爲輸入文件,將可執行文件作爲輸出文件:
$ gcc -c func.c main.c
$ gcc func.o main.o -o app.out

第一條命令只編譯不鏈接,將生成 func.o 和 main.o 兩個目標文件。第二條命令將生成的兩個目標文件生成最終的可執行文件 app.out。如果不使用 -o 選項,那麼將生成名字爲 a.out 的可執行文件。
+++++++++++++++++++++++++++++++++++++++++++++++++++

-shared
生成動態鏈接庫。輸入文件可以是源文件、彙編文件或者目標文件。

-fPIC 
作用於編譯階段,告訴編譯器產生與位置無關代碼(Position-Independent Code)

+++++++++++++++++++++++++++++++++
舉例
從源文件生成動態鏈接庫:
$ gcc -fPIC -shared func.c -o libfunc.so

從目標文件生成動態鏈接庫:
$ gcc -fPIC -c func.c -o func.o
$ gcc -shared func.o -o libfunc.so
+++++++++++++++++++++++++++++++++

摘自:http://c.biancheng.net/view/2382.html

-O0 、-O1 、-O2 、-O3
編譯器的優化選項的 4 個級別,-O0 表示沒有優化, -O1爲 缺省值,-O3 優化級別最高。

gcc 命令的常用選項

選項 解釋
-ansi 只支持 ANSI 標準的 C 語法。這一選項將禁止 GNU C 的某些特色, 例如 asm 或 typeof 關鍵詞。
-c 只編譯並生成目標文件。
-DMACRO 以字符串"1"定義 MACRO 宏。
-DMACRO=DEFN 以字符串"DEFN"定義 MACRO 宏。
-E 只運行 C 預編譯器。
-g 生成調試信息。GNU 調試器可利用該信息。
-IDIRECTORY 指定額外的頭文件搜索路徑DIRECTORY。
-LDIRECTORY 指定額外的函數庫搜索路徑DIRECTORY。
-lLIBRARY 連接時搜索指定的函數庫LIBRARY。
-m486 針對 486 進行代碼優化。
-o FILE 生成指定的輸出文件。用在生成可執行文件時。
-O0 不進行優化處理。
-O 或 -O1 優化生成代碼。
-O2 進一步優化。
-O3 比 -O2 更進一步優化,包括 inline 函數。
-shared 生成共享目標文件。通常用在建立共享庫時。
-static 禁止使用共享連接。
-UMACRO 取消對 MACRO 宏的定義。
-w 不生成任何警告信息。
-Wall 生成所有警告信息。

摘自:http://www.runoob.com/w3cnote/gcc-parameter-detail.html

GCC選項 –I,-l,-L
-I:指定第一個尋找頭文件的目錄

-L:指定第一個尋找庫文件的目錄

-l:表示在庫文件目錄中尋找指定的動態庫文件

例:

gcc –o hello hello.c –I /home/hello/include –L /home/hello/lib –lworld

/home/hello/include 作爲第一個頭文件的尋找目錄。頭文件尋找順序:/home/hello/include –> /usr/include –> usr/local/include

/home/hello/lib 作爲第一個庫文件的尋找目錄。庫文件的尋找順序:/home/hello/lib –> /lib –> /usr/lib –> /usr/local/lib

-lworld 表示在庫文件路徑中尋找libworld.so的動態庫文件

4,庫搜索路徑

靜態庫鏈接時搜索路徑順序:
1. ld會去找GCC命令中的參數-L
2. 再找gcc的環境變量LIBRARY_PATH
3. 再找內定目錄 /lib /usr/lib /usr/local/lib 這是當初compile gcc時寫在程序內的

動態鏈接時、執行時搜索路徑順序:
1. 編譯目標代碼時指定的動態庫搜索路徑
2. 環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑
3. 配置文件/etc/ld.so.conf中指定的動態庫搜索路徑
4. 默認的動態庫搜索路徑/lib
5. 默認的動態庫搜索路徑/usr/lib

有關環境變量:
LIBRARY_PATH環境變量:指定程序靜態鏈接庫文件搜索路徑
LD_LIBRARY_PATH環境變量:指定程序動態鏈接庫文件搜索路徑

摘自:http://www.sohu.com/a/165547861_777180

32位版:加上 -m32 參數,生成32位的代碼。
64位版:加上 -m64 參數,生成64位的代碼。
debug版:加上 -g 參數,生成調試信息。
release版:加上 -static 參數,進行靜態鏈接,使程序不再依賴動態庫。加上 -O3 參數,進行最快速度優化。加上-DNDEBUG參數,定義NDEBUG宏,屏蔽斷言。

當沒有-m32或-m64參數時,一般情況下會生成跟操作系統位數一致的代碼,但某些編譯器存在例外,例如——
32位Linux下的GCC,默認是編譯爲32位代碼。
64位Linux下的GCC,默認是編譯爲64位代碼。
Window系統下的MinGW,總是編譯爲32位代碼。因爲MinGW只支持32位代碼。
Window系統下的MinGW-w64(例如安裝了TDM-GCC,選擇MinGW-w64),默認是編譯爲64位代碼,包括在32位的Windows系統下。

摘自:http://blog.sina.com.cn/s/blog_53a7e8a30102vyrs.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章