Linxu自動化構建工具make/Makefile究竟時什么?
- 一、簡介
- 二、makefile文件制作(簡潔版)
- 2.1 源文件
- 2.2 makefile如何制作
- 2.2.1 依賴關系、依賴方法
- 2.2.3 偽目標(清理文件資源)
- 三、make/Makefile自動化原理
- 3.1 偽目標為什么可以重復執行?
- 3.2 make如何工作?
- 四、Makefile簡介版本
- 4.1 版本一
- 4.2 版本二
- 4,3 版本三
一、簡介
?在一個大型工程中,源文件不計其數。按照文件類型、功能、模塊不同,放在不同的目錄下。但哪些文件先編譯,哪些文件后編譯,哪些文件需沖重新編譯,甚至更為復雜的功能操作,如果依靠程序員自身來控制,不僅效率低下,而且極其容易出錯!為此,自動化構建工具誕生 —— make/Makefile
?Makefile(或makefile)是一個腳本文件;而make是一個命令工具,用于解釋Makefile中的指令,一般來說,大多數的IDE都有這個命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。當我們在Makefile中一旦寫好了編譯方式,只需要一個make命令就可完成整個工程的自動化編譯。
二、makefile文件制作(簡潔版)
2.1 源文件
這里我們給出一段各位都記憶深刻的代碼:(存在于code.c源文件
中)
#include <stdio.h> int main()
{ printf("hello world\n");printf("hello world\n");printf("hello world\n");return 0;
}
2.2 makefile如何制作
在工程中,最重要的就是通過源文件通過某種方式來形成可執行文件,以及項目資源的清理。現在的問題是如何通過makefile來達到上述目的呢?
我們只需要在Makefile文件
中輸入以下程序即可:(后續還會在修改)
mybin:code.c #如果有多個源文件,code.c后可繼續田間源文件 gcc code.c -o mybin #前面的空格只能按Tab鍵,不能輸入4個空格(語法)
.PHONY:clean #偽目標
clean: rm -f mybin
接下來我們來一一分析每段代碼是什么意思,以及如何編寫!
2.2.1 依賴關系、依賴方法
?第一行mybin:code.c
稱為依賴關系
,冒號左邊為目標文件;冒號左邊為源文件
(可以是多個)。
?第二行gcc code.c -o mybin
稱為依賴關系,及源文件通過何種方式來形成目標文件。需要特別注意的是:依賴關系前的空格只能通過Tab鍵實現,不可以是4空格或其他!!!
?比如假設我們需要通過main.c、code.c、test.c
三個源文件通過gcc來編譯形成mybin目標文件,所以代碼為:
mybin:main.c code.c test.c gcc main.c code.c test.c -o mybin
或
mybin:main.c code.c test.c gcc -o mybin main.c code.c test.c //(只需保證-o后緊跟的是目標文件即可)
2.2.3 偽目標(清理文件資源)
在上述代碼中.PHONY:xxx文件名
表示該目標文件為偽目標,表示該文件不需要依賴關系,并且總是被執行
。
現在我們分別運行偽目標文件和普通文件看看會發生什么?
【普通目標文件】:
【偽目標文件】:
?我們發現對于普通目標文件,一旦我們編譯后就不能重復編譯,否則會報make: ‘mybin' is up to date.
;但對于偽目標文件來說可以重復執行。
?為什么會這樣呢?
三、make/Makefile自動化原理
3.1 偽目標為什么可以重復執行?
?在解決這個問題之前,我們需要先了解為什么普通目標文件不可以重復執行!
?在實際工程中,一個大型項目存在眾多的源文件,我們需要對這些源文件進行編譯形成可執行文件。但一旦編譯好后,在下一次執行該文件時,我們只需要重新編譯某些內容被修改過的源文件即可。如果每次執行都需要重新編譯所有的源文件,不僅意義不大,還會導致效率大大降低!
?那程序如何發現代碼別修改過,需要重新編譯了?
?在Linux中,每個文件有3種時間:Access、Modify、change三種時間,分別代表文件被打開的時間、文件內容內修改的時間、文件屬性被修改的時間
。我們可以通過stat 文件名
來查看文件的3種時間。
?其中,Access時間比較特殊。一般而言,一個文件被訪問是非常頻繁的。由于文件存在磁盤中,如果每次進入文件都修改文件的Access時間,這也意味著存在大量的訪問磁盤的IO操作,變形的降低了操作系統的效率。為此,當代計算機一般都對更改Access時間做了次數限制,不同機器平臺存在差異。只有達到一定次數時,才會修改Access時間
。
?由于我們最終目的是得到相應的可執行程序,所以我們可以通過對比源文件和可執行文件的Modify來判斷哪些文件被修改過,需要重新編譯。即源文件第一次形成可執行文件時,可執行文件的Modify > 源文件的Modify。一旦源文件內容被修改后,此時源文件Modify被修改為最新時間,此時源文件Modify > 可執行文件的Modify。而make如果識別到源文件Modify > 可執行文件的Modify,便會對源文件進行重新編譯。
偽目標為什么可以重復執行?
?前面博主替代過,一旦文件通過.PHONY:文件名
成為偽目標,此時該文件不在需要依賴關系。這也意味這該文件不需要對比任何時間,直接執行。即可以重復執行。
3.2 make如何工作?
?在默認情況下,只要我們輸入make
命令,此時make會在當前目錄下查找名為Makefile或makefile的文件。如果找到,則它會將第一個目標文件作為最終的目標文件。
?如果第一個目標文件文件不存在,或是第一個目標文件所依賴的后面的 .o 文件的文件修改時間要比第一個目標文件新,那么,他就會執行后面所定義的命令來生成這個文件。如果第一個目標文件所依賴的.o文件也不存在,那么make會在當前文件中找目標為.o文件的依賴性,如果找到則再根據那一個規則生成.o文件。
?這就是整個make的依賴性,make會一層又一層地去找文件的依賴關系,直到最終編譯出第一個目標文件。在找尋的過程中,如果出現錯誤,比如最后被依賴的文件找不到,那么make就會直接退出,并報錯,而對于所定義的命令的錯誤,或是編譯不成功,make根本不理。make只管文件的依賴性,即,如果在找了依賴關系之后,冒號后面的文件還是不在,那么就不工作了。
四、Makefile簡介版本
比如假設我們需要通過main.c、code.c、test.c
三個源文件通過gcc來編譯形成mybin目標文件,這里有3個版本。各位自行選擇。
4.1 版本一
這個就是最簡單版本,就不多說了。
mybin:code.c gcc main.c、code.c、test.c -o mybin #前面的空格只能按Tab鍵,不能輸入4個空格(語法)
.PHONY:clean #偽目標
clean: rm -f main.c、code.c、test.c
4.2 版本二
在Makefile中,我們可以在指令前加上@
符號,可以不在顯示屏上回顯文件執行的指令。同時$@
表示冒號左邊的目標文件,$^
來表示冒號右邊的所有源文件。
所以上述代碼可修改如下:
mybin:main.c、code.c、test.c gcc &^ -o $@ #前面的空格只能按Tab鍵,不能輸入4個空格(語法)
.PHONY:clean #偽目標
clean: rm -f target
4,3 版本三
在make/Makefile中,支持變量化處理
。有點類似于宏替換,具體如下:
cc=gcc
target=mybin.exe
src=main.c code.c test.c
#使用上述變量時,我們僅需通過$(變量)即可使用$(target):$(src) $(cc) &^ -o $@ #前面的空格只能按Tab鍵,不能輸入4個空格(語法)
.PHONY:clean #偽目標
clean: rm -f target