gcc ------->默認編譯c文件(gcc xxx -lstdc++連接到c++庫編譯c++,g++默認編譯c++)mysql
一.CC編譯程序過程分四個階段
◆ 預處理(Pre-Processing)
◆ 編譯(Compiling)
◆ 彙編(Assembling)
◆ 連接(Linking)c++
1.1 預處理(Pre-Processing)程序員
gcc -E test.c -o test.i 或 gcc -E test.c
能夠輸出test.i文件中存放着test.c經預處理以後的代碼。打開test.i文件,看一看,就明白了。後面那條指令,是直接在命令行窗口中輸出預處理後的代碼.sql
gcc的-E選項,可讓編譯器在預處理後中止,並輸出預處理結果。預處理結果就是將#include等相似的文件中的內容插入到當前文件中。ide
1.2 編譯(Compiling)函數
預處理以後,可直接對生成的test.i文件編譯,生成彙編代碼:工具
gcc -S test.i -o test.s
gcc的-S選項,表示在程序編譯期間,在生成彙編代碼後,中止,-o輸出彙編代碼文件。ui
1.3 彙編(Assembling)spa
對於生成的彙編代碼文件test.s,gas彙編器負責將其編譯爲目標文件,以下:操作系統
gcc -c test.s -o test.o
1.4 連接(Linking)
gcc鏈接器是gas提供的,負責將程序的目標文件與所需的全部附加的目標文件鏈接起來,最終生成可執行文件。附加的目標文件包括靜態鏈接庫和動態鏈接庫。
對於上一小節中生成的test.o,將其與C標準輸入輸出庫進行鏈接,最終生成程序test
gcc test.o -o test
這個程序,一步到位的編譯指令是:
gcc test.c -o test
二:庫文件連接
開發軟件時,徹底不使用第三方函數庫的狀況是比較少見的,一般來說都須要藉助許多函數庫的支持纔可以完成相應的功能。從程序員的角度看,函數庫實際上就是一些頭文件(.h)和庫文件(so、或lib、dll)的集合。。雖然Linux下的大多數函數都默認將頭文件放到/usr/include/目錄下,而庫文件則放到/usr/lib/目錄下;Windows所使用的庫文件主要放在Visual Stido的目錄下的include和lib,以及系統文件夾下。但也有的時候,咱們要用的庫再也不這些目錄下,因此GCC在編譯時必須用本身的辦法來查找所須要的頭文件和庫文件。(頭文件的路徑用-I,庫文件路徑用-L,好比說-I/usr/myinclude -L/usr/mylib)
-l參數就是用來指定程序要連接的庫,-l參數緊接着就是庫名,那麼庫名跟真正的庫文件名有什麼關係呢?就拿數學庫來講,他的庫名是m,他的庫文件名是libm.so,很容易看出,把庫文件名的頭lib和尾.so去掉就是庫名了(把函數庫命名爲「lib「是UNIX的慣例,「.so」是共享文件庫的標準擴展名)
2.1 編譯成可執行文件
首先咱們要進行編譯test.c爲目標文件,這個時候須要執行
gcc –c –I /usr/dev/mysql/include test.c –o test.o
2.2 連接
最後咱們把全部目標文件連接成可執行文件:
gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test
Linux下的庫文件分爲兩大類分別是動態連接庫(一般以.so結尾)和靜態連接庫(一般以.a結尾),兩者的區別僅在於程序執行時所需的代碼是在運行時動態加載的,仍是在編譯時靜態加載的。
2.3 強制連接時使用靜態連接庫
默認狀況下, GCC在連接時優先使用動態連接庫,只有當動態連接庫不存在時才考慮使用靜態連接庫,若是須要的話能夠在編譯時加上-static選項,強制使用靜態連接庫。
在/usr/dev/mysql/lib目錄下有連接時所須要的庫文件libmysqlclient.so和libmysqlclient.a,爲了讓GCC在連接時只用到靜態連接庫,可使用下面的命令:
gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test
靜態庫連接時搜索路徑順序:
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環境變量:指定程序動態連接庫文件搜索路徑
總結:源文件首先會生成中間目標文件,再由中間目標文件生成執行文件。在編譯時,編譯器只檢測程序語法,和函數、變量是否被聲明。若是函數未被聲明,編譯器會給出一個警告,但能夠生成Object File。而在連接程序時,連接器會在全部的Object File中找尋函數的實現,若是找不到,那到就會報連接錯誤碼
三:makefile工具
make是一個命令工具,是一個解釋makefile中指令的命令工具,make會在當前目錄下找名字叫「Makefile」或「makefile」的文件。make會一層又一層地去找文件的依賴關係(若是該過程文件比生成的目標文件新,需從新編譯),直到最終編譯出第一個目標文件。
Makefile的規則
target ... : prerequisites ...
command
...
...
target這一個或多個的目標文件依賴於prerequisites中的文件,其生成規則定義在command中。說白一點就是說,prerequisites中若是有一個以上的文件比target文件要新的話,command所定義的命令就會被執行。這就是Makefile的規則。也就是Makefile中最核心的內容。
3.1 基礎makefile
target : prerequisites1.o prerequisites2.o prerequisites3.o / cc -o target prerequisites1.o prerequisites2.o prerequisites3.o display.o prerequisites1.o : prerequisites1.c prerequisites1.h cc -c main.c prerequisites2.o : prerequisites1.c prerequisites2.h cc -c prerequisites2.c prerequisites3.o : prerequisites3.c prerequisites3.h cc -c prerequisites3.c clean : rm target prerequisites1.o prerequisites2.o prerequisites3.o
反斜槓(/)是換行符的意思。在這個makefile中,目標文件(target)包含:中間目標文件(*.o),依賴文件(prerequisites)就是冒號後面的那些 .c 文件和 .h文件。每個 .o 文件都有一組依賴文件,而這些 .o 文件又是執行文件 target 的依賴文件。依賴關係的實質上就是說明了目標文件是由哪些文件生成的。
在定義好依賴關係後,後續的那一行定義瞭如何生成目標文件的操做系統命令,必定要以一個Tab鍵做爲開頭。make並無論命令是怎麼工做的,他只管執行所定義的命令。make會比較targets文件和prerequisites文件的修改日期,若是prerequisites文件的日期要比targets文件的日期要新,或者target不存在的話,那麼,make就會執行後續定義的命令。
3.2 變量makefile
上例看到編譯目標文件時[.o]文件的字符串被重複了兩次,若是咱們的工程須要加入一個新的[.o]文件,那麼咱們須要在兩個地方加(應該是三個地方,還有一個地方在clean中)。咱們聲明一個變量OBJ等於依賴的[.o]文件,而後在咱們的makefile中以「$(objects)」的方式來使用這個變量
3.3 make自動推導
GNU的make很強大,它能夠自動推導文件以及文件依賴關係後面的命令,因而咱們就不必去在每個[.o]文件後都寫上相似的命令。make看到一個[.o]文件,它就會自動的把[.c]文件加在依賴關係中,若是make找到一個prerequisite1.o,那麼prerequisite1.c,就會是prerequisite1.o的依賴文件。而且 cc -c prerequisite1.c 也會被推導出來。以下代碼:
OBJ = prerequisites1.o prerequisites2.o prerequisites3.o target : $(OBJ)/ cc -o target $(OBJ) prerequisites1.o : prerequisites1.h prerequisites2.o : prerequisites2.h prerequisites3.o : prerequisites3.h .PHONY : clean clean : rm target $(OBJ)
這種方法,也就是make的「隱晦規則」。上面文件內容中,「.PHONY」表示,clean是個僞目標文件。