make
此條目需要補充更多來源。 (2019年4月21日) |
編程範型 | 巨集, 宣告式編程 |
---|---|
設計者 | 斯圖亞特·費爾德曼 |
面市時間 | 1976年4月 |
實作語言 | C 語言 |
操作系統 | 類 Unix 系統 |
檔案格式 | Makefile |
Make是一個在軟件開發中所使用的構建工具,用於自動化建構軟體。 它通過一個名為 Makefile 的文本文件來描述源代碼文件之間的依賴關係和構建規則。 Make 會根據這些規則和依賴關係,判斷哪些文件需要重新編譯,並執行相應的編譯命令,以確保最終生成可執行文件或其他目標文件(這些目標被稱為「target」)。 大多數情況下,它被用來編譯源代碼,生成結果代碼,然後把結果代碼連接起來生成可執行文件或者庫文件。
許多現代軟體的開發環境中(如Microsoft Visual Studio),集成開發環境已經取代make,但是在Unix環境中,仍然有許多工程師採用make來協助軟體開發。
起源
[編輯]目前雖有眾多依賴關係檢查工具,但是make是應用最廣泛的一個。這要歸功於它被包含在Unix系統中。[1]斯圖亞特·費爾德曼(Stuart Feldman)在1977年在貝爾實驗室(Bell Labs)里製作了這個軟件。[2][3][1]2003年,斯圖亞特·費爾德曼因發明了這樣一個重要的工具而接受了美國計算機協會(ACM)頒發的軟件系統獎。[4]
在make誕生之前,編譯工作主要依賴於操作系統裡面的類似於「make」、「install」功能的shell腳本。它可以批量執行生成目標的命令,並且可以完成依賴關係的檢查。這是向現代編譯環境發展的重要一步。
不同版本
[編輯]make程序已被使用者多次重/改寫,其中包括幾次用相同的文件格式和算法原理重新編寫,並且依照不同需要添加了一些不常見的改良。
GNU make
[編輯]GNU make仿照make的標準功能(透過clean-room工程)重新改寫,並加入作者覺得值得加入的新功能,常和GNU編譯系統一起被使用,是大多數GNU Linux安裝的一部分。
BSD make
[編輯]BSD make是從Adam de Boor的製作的版本上發展成。它編譯目標的時候有並行計算的能力。它在FreeBSD,NetBSD和OpenBSD中不同程度的修改下存活了下來。
Microsoft nmake
[編輯]廣泛應用於微軟的Windows,微軟的nmake是 Visual Studio 隨附的命令行工具,不要與來自AT&T和貝爾實驗室的Unix系統nmake混淆。
優點和缺點
[編輯]就像其他和make有着悠久歷史的軟件一樣,make有着很多的擁護者和反對者。它的很多問題因現代大型的軟件項目的出現而暴露出來。但是很多人爭論說它在常見的情況下可以很好的工作,而且使用非常的簡單,功能強大,表達清楚。無論如何,make仍然被用來編譯很多完整的操作系統,而且現在替代品們在基本的操作上與它沒有太大差別。
隨着現代的集成開發環境(IDE)的誕生,特別是非Unix的平台上,很多程序員不再手動管理依靠關係檢查,甚至不用去管哪些文件是這個項目的一部分,而是把這些任務交給了他們的開發環境去做。類似的,很多現代的編程語言有自己特別的高效的依賴關係的設置方法。
Makefile
[編輯]規則
[編輯]makefile的格式是:
# 用“#”号表明注释。 target(要生成的文件): dependencies(被依赖的文件) # 命令前面用的是“tab”而非空格。误用空格是初学者容易犯的错误! Tab ↹命令1 Tab ↹命令2 Tab ↹命令3 . . . Tab ↹命令n # 可以使用“\”表示续行。注意,“\”之后不能有空格!
- target, dependencies和命令構成了一個makefile里的一個「規則」,規則指示make何時以及如何重新生成target或執行target下的命令
- target通常是我們要生成的文件的名字,擺放的順序不重要,但第一個target是默認的target。當make不帶參數時,自動執行第一個target。target也可以是要求make完成的動作,執行這種target後並不能得到和target同名的文件,因此,也稱為偽target(phony target)。
- dependencies是生成target所需的文件名列表。依賴可以為空,常用的「clean」target就常常沒有依賴,只有命令。若依賴不為空,則make會先檢查依賴的「規則」。依賴規定了何時重新執行target下命令。若任何依賴比target更新 (由於執行了依賴的「規則」的命令或用戶修改了依賴),make則會重新執行target下的命令。
- 命令可以是任何一個shell能運行的命令。
示例
[編輯]舉例來說明makefile的結構和make如何運作。
editor: main.o text.o
gcc -o editor main.o text.o
main.o: main.c def.h
gcc -c main.c
text.o: text.c com.h
gcc -c text.c
install:editor
mv editor /usr/local
當我們輸入:
make 或者 make editor
當editor這個target文件不存在,或者main.o、text.o這兩個依賴文件被修改,都會導致make調用其下的命令「gcc -o editor main.o text.o」;接下來,由於引用到main.o和text.o,make會檢查main.o的依賴main.c、def.h有無更新,如果有,則執行其下的命令「gcc -c main.c」;同樣的道理,也適用於text.o。 於是,可有幾種不同的輸出:
- 第一次運行:
gcc -c main.c gcc -c text.c gcc -o editor main.o text.o
- main.c或/和def.h有修改:
gcc -c main.c gcc -o editor main.o text.o
- text.c或/和com.h有修改:
gcc -c text.c gcc -o editor main.o text.o
- main.c和text.c均有修改:
gcc -c main.c gcc -c text.c gcc -o editor main.o text.o
當我們輸入:
make install
make會檢查install的依賴editor是否是最新,如果是,則執行其下的命令「mv editor /usr/local」。由於這個過程並沒有產生名為「install」的文件,所以,install是一個假目標。
巨集
[編輯]「巨集」指的是用一個字符串代替另一個字符串的功能。在makefile中可以使用「=」號來定義巨集,使用「$(巨集名)」來使用巨集;還可以用「+=」追加巨集的內容。習慣上,巨集名使用大寫。承接上面的例子:
OBJECTS = main.o text.o
INSTALL_PATH = /usr/local
editor: $(OBJECTS)
gcc -o editor $(OBJECTS)
main.o: main.c
gcc -c main.c
text.o: text.c
gcc -c text.c
install:editor
mv editor $(INSTALL_PATH)
參見
[編輯]參考資料
[編輯]- ^ 1.0 1.1 Thompson, T. J. Designer's Workbench: Providing a Production Environment. Bell System Technical Journal. November 1980, 59 (9): 1811–1825. doi:10.1002/j.1538-7305.1980.tb03063.x.
In the general maintenance of DWB, we have used the Source Code Control System and make utility provided by the PWB/UNIX* interactive operating system.
- ^ V7/usr/src/cmd/make/ident.c. tuhs.org. 1 September 2013 [18 March 2018]. (原始內容存檔於2013-09-01).
- ^ Feldman, S. I. Make --- A Program for Maintaining Computer Programs. Software: Practice and Experience. April 1979, 9 (4): 255–265 [11 May 2016]. doi:10.1002/spe.4380090402. (原始內容存檔於2020-09-14).
- ^ Matthew Doar. Practical Development Environments. O'Reilly Media. 2005: 94. ISBN 978-0-596-00796-6.