========================【編譯和連結】===============================
首先要把源檔案編譯成中間代碼檔案。
UNIX下是 .o 檔案,即 Object File,即目标檔案。這個動作叫做編譯(compile),由編譯器完成(gcc)。
然後再把大量的Object File合成執行檔案,這個動作叫作連結(link),由連結器完成(ld)。
編譯時:
編譯器需要的是文法的正确,函數與變量的聲明的正确。
對于後者,通常是你需要告訴編譯器頭檔案的所在位置(頭檔案中應該隻是聲明,而定義應該放在C/C++檔案中)。
隻要所有的文法正确,編譯器就可以編譯出中間目标檔案。
一般來說,每個源檔案都應該對應于一個中間目标檔案(O檔案或是OBJ檔案)。
連結時:
主要是連結函數和全局變量,
是以,我們可以使用這些中間目标檔案(O檔案或是OBJ檔案)來連結我們的應用程式。
連結器并不管函數所在的源檔案,隻管函數的中間目标檔案(Object File)。
在大多數時候,由于源檔案太多,編譯生成的中間目标檔案太多,而在連結時需要明顯地指出中間目标檔案名。
這對于編譯很不友善,是以,我們要給中間目标檔案打個包,在Windows下這種包叫“庫檔案”(Library File),
也就是 .lib 檔案,在UNIX下,是Archive File,也就是 .a 檔案(靜态庫)。
源檔案首先會生成中間目标檔案,再由中間目标檔案生成可執行檔案。
在編譯時,編譯器隻檢測程式文法,和函數、變量是否被聲明。
如果函數未被聲明,編譯器會給出一個警告,但可以生成Object File。
而在連結程式時,連結器會在所有的Object File中找尋函數的實作,
如果找不到,那到就會報連結錯誤碼(Linker Error)。
=========================【make和makefile】===========================
如果手動操作gcc,ld來編譯代碼最終生成可執行檔案,對于代碼量較大的工程來說,是很困難,且效率低下。
這時候就需要自動化編譯。
makefile和make就是自動化編譯的一種方法;
如果是一個大系統,存在很多個子產品,那麼手工編譯的方法就不适用了。
為此,在Linux系統中,專門提供了一個make指令來自動維護目标檔案。
makefile:
makefile是一個檔案,用于描述編譯的規則;
一個工程中的源檔案不計其數,按類型,功能,子產品分别放在若幹個目錄中。
makefile定義了一系列的規則來指定,哪些檔案需要先編譯,哪些檔案需要後編譯,
哪些檔案需要重新編譯,甚至于進行更複雜的功能操作。
makefile檔案描述了整個工程所有檔案的編譯順序,編譯規則。
makefile有自己的書寫格式,關鍵字,函數。還可以使用shell所提供的任何指令來完成想要的工作。
makefile就像一個shell腳本一樣,其中也可以執行作業系統的指令。
一旦寫好,隻需要一個make指令,整個工程完全自動編譯,極大的提高了軟體開發的效率。
make:
make是指令工具,用來解釋makefile的指令的指令工具;
make指令執行時,需要一個 makefile 檔案,以告訴make指令需要怎麼樣的去編譯和連結程式。
與手工編譯和連接配接相比,make指令的優點在于他隻更新修改過的檔案(在Linux中,一個檔案被建立或更新後有一個最後修改時間,make指令就是通過這個最後修改時間來判斷此檔案是否被修改)。
而對沒修改的檔案則置之不理,并且make指令不會漏掉一個需要更新的檔案。
make指令當然不會自己知道這些依賴關系,而需要程式員将這些依賴關系寫入一個叫makefile的檔案中。
make指令教程:
http://www.ruanyifeng.com/blog/2015/02/make.html
Makefile由淺入深--教程、幹貨:
https://zhuanlan.zhihu.com/p/47390641
=======================【configure檔案】===============================
對于很大的項目來說,自己手寫Makefile非常麻煩,而标準的GNU軟體(如Apacle)都是運作一個configure腳本檔案來自動産生 Makefile;
這裡同時還涉及到代碼移植性的問題,即你釋出的源代碼,要在别人的(類unix)環境中編譯成功,這對編寫makfile檔案提出了不少挑戰。
這裡有兩個問題:
1、工程很大時,手工編寫makefile檔案非常麻煩;
2、makefile檔案要保證源代碼放到其他環境中時能編譯通過;
這就對makefile檔案提出了兩個要求:
1、自動生成makfile檔案;
2、生成适用各個平台具體環境的makefile檔案,而且還可以友善使用者通過簡單指令進行個性化修改;
configure 是一個腳本,它能設定源程式來适應各種不同的作業系統平台,并且根據不同的系統來産生合适的Makefile ,
進而可以使你的源代碼能在不同的作業系統平台上被編譯出來。
configure很好地解決了上述兩大需求;
那麼configure腳本是怎麼來的?下一節介紹
源碼編譯安裝步驟:
從網上下載下傳的許多源碼的編譯和安裝過程非常簡單,壓縮後需要的操作隻有三步:
./configure
make
make install
即我們隻要運作./configure,這個腳本就能檢測目前系統的一些特性,自動生成适合目前平台的makefile檔案;
運作make,則會跟進makefile的規則,對源碼進行編譯。
GNU build system:
這種軟體編譯和安裝的架構其實是有一套标準的,即GNU項目提出的GNU build system。
GNU Build System指的是這樣一種源碼編譯系統:
它符合GNU Coding Standards标準,有configure腳本、Makefile腳本等,
并且這些腳本遵循一定的最小接口規範,使得使用者可以使用一些簡單的指令(如:./configure,make,make install)在不同的系統架構上編譯并安裝GNU工程。
=========================【autotools工具套件】===================================
一個符合GNU Build System标準的源代碼,
隻要使用“./configure”,“make”,“make install”就可以把程式安裝到Linux系統中去了。
這将特别适合想做開放源代碼軟體的程式開發人員。
為了使源代碼實作GNU Build System标準,這對軟體開發人員來說是巨大的挑戰。
編寫一個簡單的makefile還行。但是編寫一個符合自由軟體慣例的Makefile就不那麼容易了。
Autotools就是一系列幫助開發人員建立GNU Build System的開發套件。
用于自動編譯源碼并實作類Unix系統間的可移植性。
這個工具出現的原因是因為軟體的可移植性面臨巨大的挑戰:系統間的C編譯器不同、庫函數不相容等。
Autotools是GNU工具鍊的一員,它的另一個名稱是GNU build system。
它是一個程式開發工具套件。這裡我們要用到的是automake、autoconf、autoheader、autoscan和alocal。概念上說,它們的從屬關系如下圖:

auotscan會周遊指定源碼目錄下的所有檔案,找出其中需要特别指定的宏指令。
它生成的檔案configure.scan是一個藍本檔案,即隻給出了最基本的宏語句。
開發人發在這個檔案中進行功能添加後,應該把它改名為configure.ac(也可以改為configure.in)。
aclocal是一個perl 腳本程式,它根據configure.in檔案的内容,自動生成aclocal.m4檔案、
aclocal的定義是:"aclocal - create aclocal.m4 by scanning configure.ac"。
aclocal.m4檔案可以用來包含該源碼包自定義的宏。
autoconf是用來産生configure檔案的。configure是一個腳本,
它能設定源程式來适應各種不同的作業系統平台,并且根據不同的系統來産生合适的Makefile,
autoconf程式更像是一個宏展開工具,它使用M4宏處理工具把configure.ac中的宏定義展開為configure的宏實作。
這些宏的定義在一些Autoconf工程檔案中。
autoconf 需要GNU m4 宏處理器來處理aclocal.m4 ,生成configure 腳本。
我們使用automake --add-missing來産生Makefile.in。
選項--add-missing的定義是 "add missing standard files to package",
它會讓automake加入一個标準的軟體包所必須的一些檔案。
automake 會根據你寫的Makefile.am 來自動生成Makefile.in
Makefile.am 中定義的宏和目标, 會指導automake 生成指定的代碼。
我們用automake産生出來的Makefile.in檔案是符合GNU Makefile慣例的,
接下來我們隻要執行configure這個shell腳本,會跟進Makefile.in産生合适的Makefile檔案了。
autoheader工具會産生config.h.in檔案。
========================【CMake】===================================