GUN make (8) make的隱含規則

隱含規則爲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命令創建這樣一個空的源文件。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章