天天看點

從源代碼到可執行檔案

========================【編譯和連結】===============================

首先要把源檔案編譯成中間代碼檔案。

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】===================================