我過去認為 makefile 只是一種將一組組的 shell 命令列出來的簡便方法;過了一段時間我了解到它們是有多麼的強大、靈活以及功能齊全。這篇文章帶你領略其中一些有關規則的特性。
備註:這些全是針對 GNU Makefile 的,如果你希望支援 BSD Makefile ,你會發現有些新的功能缺失。感謝 zge 指出這點。
規則是指示 make
應該如何並且何時構建一個被稱作為目標的檔案的指令。目標可以依賴於其它被稱作為前提的檔案。
你會指示 make
如何按步驟構建目標,那就是一套按照出現順序一次執行一個的 shell 命令。語法像這樣:
target_name : prerequisites recipe
一但你定義好了規則,你就可以通過從命令列執行以下命令構建目標:
$ make target_name
目標一經構建,除非前提改變,否則 make
會足夠聰明地不再去執行該步驟。
前提表明了兩件事情:
make
假定目的應當被構建。如果你想要定義一個順序但是你不想在前提改變的時候重新構建目標,你可以使用一種特別的叫做“唯順序”的前提。這種前提可以被放在普通的前提之後,用管道符(|
)進行分隔。
為了便利,make
接受目標和前提的樣式。通過包含 %
符號可以定義一種樣式。這個符號是一個可以匹配任何長度的文字元號或者空隔的萬用字元。以下有一些範例:
%
:匹配任何檔案%.md
:匹配所有 .md
結尾的檔案prefix%.go
:匹配所有以 prefix
開頭以 .go
結尾的檔案有一系列目標名字,它們對於 make
來說有特殊的意義,被稱作特殊目標。
你可以在這個文件發現全套特殊目標。作為一種經驗法則,特殊目標以點開始後面跟著大寫字母。
以下是幾個有用的特殊目標:
.PHONY
:向 make
表明此目標的前提可以被當成偽目標。這意味著 make
將總是執行,無論有那個名字的檔案是否存在或者上次被修改的時間是什麼。.DEFAULT
:被用於任何沒有指定規則的目標。.IGNORE
:如果你指定 .IGNORE
為前提,make
將忽略執行步驟中的錯誤。當你需要以你指定的改動方式改變一個變數的值,替代就十分有用了。
替代的格式是 $(var:a=b)
,它的意思是獲取變數 var
的值,用值裡面的 b
替代詞末尾的每個 a
以代替最終的字串。例如:
foo := a.obar : = $(foo:.o=.c) # sets bar to a.c
注意:特別感謝 Luis Lavena 讓我們知道替代的存在。
檔案檔案是用來一起將多個資料文件(類似於壓縮檔案的概念)收整合一個檔案。它們由 ar
Unix 工具所構建。ar
可以用於為任何目的建立檔案,但除了靜態庫,它已經被 tar
大量替代。
在 make
中,你可以使用一個檔案檔案中的單獨一個成員作為目標或者前提,就像這樣:
archive(member) : prerequisite recipe
關於 make
還有更多可探索的,但是至少這是一個起點,我強烈鼓勵你去檢視文件,建立一個笨拙的 makefile 然後就可以探索它了。