隱含規則爲make提供了一類目標文件通用方法,不需要在makefile中明確的給出重建特定目標文件所需的細節描述。
只要目標文件中除後綴以外其他部分相同,make都能夠使用若干隱含規則來最終產生這個目標文件。
對應關係:
EXENAME.o 對應 EXENAME.c
EXENAME 對應 EXENAME.o
1.隱含規則的使用
foo:foo.o
cc -o foo foo.o $(CFLAGS) $(LDFLAGS)
這裏並沒有給出重建文件foo.o的規則,在make執行這條規則的時候,無論foo.o存在與否,都會試圖根據隱含規則來重建這個文件。
可以使用 -r 或者 -R 參數取消隱含規則
2.常用隱含規則
編譯c程序:
N.o 自動由 N.c 生成,執行命令 $(CC) -c $(CPPFLAGS) $(CFLAGS)
鏈接單一的object文件
N 自動由 N.o 生成,執行命令 $(CC) $(LDFLAGS) N.o $(LOADLIBES) $(LDLIBS)
3. 隱含變量
內嵌隱含變量的命令中,所使用的變量都是預定義的變量,我們稱之爲隱含變量。
在makefile中,通過命令行參數或者設置系統環境變量來對它進行重定義。
隱含規則中所使用的隱含變量分爲兩類:
- 代表一個命令的名字。
- 代表執行這個程序使用的參數。
3.1 代表命令的變量
AR 函數庫打包程序,可以創建靜態庫.a文檔,默認是 ar
AS 彙編程序,默認 as
CC c編譯程序,默認是cc
CPP c程序的預處理器,默認是 $(CC) -E
YACC yacc文法分析器,默認命令是 yacc
RM 刪除命令, 默認是rm -f
3.2 代表參數的變量
ARFLAGS 執行AR命令的命令行參數,默認是 rv
ASFLAGS 執行彙編語器 AS 的命令行參數
CFLAGS 執行CC編譯器的命令行參數
YFLAGS yacc文法分析器參數
4. make隱含規則鏈
如果一個目標文件需要一系列隱含規則才能完成它的創建,則把這個系列稱爲一個 鏈。
中間過程文件:
文件N.c不存在也沒有在makefile中提及的情況,只要存在N.y這個文件,那麼make也會經過這兩個步驟來重建N.o :
N.y -> N.c -> N.o
其中,N.c就在中間過程文件。並且會自動加入到依賴關係鏈中。
在Makefile中明確提及的文件都不被作爲中間過程文件來處理。
當中間文件不存在時:
- 對於一個普通文件,因爲makefile沒有提及,則此文件可能是一個目標的依賴,make在執行它所在的規則前會試圖重建它。
- 對於一箇中間文件,因爲沒有明確提及,make不會去試圖重建它。除非這個中間文件所依賴的文件被更新。
如果make在執行時需要一箇中間過程文件,那麼默認的動作是:這個中間過程文件在make執行結束後會被刪除。
5. 模式規則
在模式規則中,目標名中需要包含有模式字符 % ,其可以匹配任何非空字符串。
模式字符 % 的匹配和替換髮生在規則中所有變量和函數引用展開之後。
普通多目標規則(多目標中沒有模式):
- 將每一個目標作爲一個獨立的規則來處理,所以多個目標就對應多個獨立的規則。
多目標模式規則:
- 所有規則的目標 共同擁有 依賴文件和規則的命令行,當文件符合多個目標模式中的 任何一個時,規則定義的命令就有可能將會執行。
- 在執行一次命令之後,規則不會再去檢查是否需要重建符合其他模式的目標。
- 當一個目標文件同時符合多個目標模式時,make將會把 第一個 目標匹配的模式規則作爲重建它的規則。
- makefile中明確指定的模式規則會覆蓋隱含模式規則。
比如有如下 多目標模式 規則:
%.o %.x : %.c
$(CC) $(CFLAGS) $< -o $@
當執行make foo.o foo.c時,會只看到第一個目標foo.o被創建,同時make會提示foo.x文件是最新的,其實foo.x並沒有被創建。
6. 自動化變量
自動化變量的取值取決於所執行的規則的目標和依賴的文件名。
有以下自動化變量:
$@ 表示規則的文件名
$% 當規則的目標文件是一個靜態庫文件時,代表靜態庫的一個成員名。如果目標不是靜態庫,其值爲空。
$< 規則的第一個依賴文件名。
$? 所有比目標文件更新的依賴文件列表,空格分隔。
$^ 規則的所有依賴文件列表,使用空格分隔。
$+ 類似於$^,但是保留了依賴文件中重複出現的文件。
$* 在模式規則和靜態模式規則中,代表 莖,莖 是目標模式中 % 所代表的部分。
$(@D) 表示目標文件的目標部分,不包括斜槓。如果$@是 dir/foo.o 則$(@D) 爲 dir
$(@F) 表示目標文件完整文件名中除目錄以外的部分。如果$@是 dir/foo.o 則$(@F) 爲 foo.o
$(*D)
$(*F) 表示目標 莖 中的目錄和文件名部分。
$(%D)
$(%F) 當目標爲靜態庫時,表示庫文件成員中目錄部分和文件名部分。
$(<D)
$(<F) 表示規則中第一個依賴文件的目錄部分和文件名部分。
$(^D)
$(^F) 表示規則中所有依賴文件的目錄部分和文件名部分。
$(+D)
$(+F) 表示規則中所有依賴文件的目錄部分和文件名部分(可存在重複文件)。
$(?D)
$(?F) 表示被更新的依賴文件的目錄部分和文件名部分。
7. 萬用規則
當模式規則的目標只有一個模式字符 % ,我們稱之爲 萬用規則。
使用萬用規則會導致make執行時考慮的情況變多,從而效率降低,所以需要對萬用規則的使用進行限制:
將萬用規則設置爲最終規則,定義時使用雙冒號規則。作爲最終規則,此規則只有在它的依賴文件存在時才能被應用。即使它的依賴可以由隱含規則創建也不行。
8.缺省規則
在make執行過程中無法爲一個文件找到合適的重建規則,那麼就用缺省規則去創建。
比如:
%::
touch $@
執行make時,對所有不存在的.c文件將會使用touch命令創建這樣一個空的源文件。