make編譯筆記(五)隱含規則

2020-08-08 19:02:27

隱含規則

隱含規則是一種慣例,一種隱含的,早約定好的,不需要再寫出來的規則。例如把.c檔案編譯成.o檔案。隱含規則會使用一些系統變數,可以改變這些系統變數的值來定製隱含規則的執行時參數,如系統變數CFLAGS可以控制編譯時的編譯器參數。可以通過模式規則的方式寫下自己的隱含規則,顯得智慧和清楚。用後綴規則定義隱含規則會有許多限制,但可以保證Makefile的相容新。

使用隱含規則

例:

foo:foo.o bar.o
    cc -g foo foo.o bar.o $(CFLAGS) &(LDFLAGS)

make的隱含規則會自動推導foo.o和bar.o這兩個目標的依賴檔案和生成命令。make在自己的隱含規則庫中尋找可以用的規則,有就用,找不到就報錯。

如果僞.o檔案書寫了規則,那麼make就不會自動推導並呼叫隱含規則,按照寫好的規則執行。

隱含規則一覽

如果不明確的寫下規則,那麼make就在所有預設的隱含規則中尋找所需要的規則和命令。可以使用make的參數-r或--no-builtin-rules選項來取消所有的預設值的隱含規則。即使使用了-r參數,某些隱含規則還是會生效的,因爲許多隱含是使用後綴規則來定義的。預設的後綴列表(在後綴列表中的隱含規則生效)有:.out、.a、.ln、.o、.c、.cc、.C、.p、.f、.F、.r、.y、.l、.s、.S、.mod、.sym、.def、.h、.info、.fvi、.tex、.txeinfo、.texi、.txinfo、.w、.ch、.web、.sh、.elc、.el。

常用隱含規則:

  • 編譯C程式的隱含規則

檔名.o的依賴目標會自動推導爲檔名.c,並且其生成的命令是$(CC) -c $(CPPFLAGS) $(CFLAGS)

  • 編譯C++程式的隱含規則

檔名.o的依賴目標會自動推導爲檔名.cc或檔名.C,並且其生成的命令是$(CXX) -c $(CPPFLAGS) $(CFLAGS)

建議使用.cc作爲C++原始檔的後綴

  • 鏈接Object檔案的隱含規則

檔名目標依賴於檔名.哦,通過C的編譯器來執行鏈接程式生成(一般是ld),

其生成的命令是$(CC) $(LDFLAGS) 檔名.o $(LOADLIBES) $(LDLIBS)。

這個規則對於只有一個原始檔的程工程有效,同時對多個Object檔案有效。

隱含規則使用變數(部分)

隱含規則中使用的變數分爲兩種,一種是命令相關的;另一種是參數相關的

  • 命令的變數
變數 說明
AR 函數庫打包程式。預設命令是ar
AS 彙編語言編譯程式。預設命令是as
CC C語言編譯程式。預設命令是cc
CXX

C++語言編譯程式。預設命令是g++

CPP C語言的前處理器(輸出是標準輸出裝置)。預設命令是co
RM 刪除檔案命令。預設命令是rm -f
  • 命令參數的變數(如果沒有指明預設值,那麼預設值都爲空)
變數 說明
ARLAGS 函數庫打包程式AR命令的參數,預設呂、
ASFLAGS 彙編語言編譯器參數(當明顯呼叫.s或.S檔案)
CFLAGS C語言編譯器參數
CXXFLAGS C++語言編譯器參數
CPPFLAGS C前處理器參數 (C和Fortran編譯器也會用到)

隱含規則鏈

有時一個檔案可以由一系列隱含規則進行建立。例如檔案A.o的建立過程是先執行yacc由B.y生成B.c,然後執行cc將B.c編譯成B.o,這樣一個系列稱爲一個鏈。

在Makefile中明確提及的所有檔案都不會被作爲中間過程檔案來處理(預設),但可以使用特殊目標.INTERMEDIATE來宣告哪些檔案需要被作爲中間過程檔案來處理(在make執行結束後被刪除)。希望保留中間檔案,使用特殊目標.SECONDARY來宣告檔案。

需要保留中間過程檔案還有另一種方式。例如需要保留所有的.o中間過程檔案,可以將.o檔案的模式%。o作爲特殊目標.PRECIOUS的依賴。

一個鏈可以包含多個隱含規則的呼叫,但一個隱含規則在一個鏈中只能出現一次,以免出現make進入無限回圈。

模式規則

可以使用模式規則來定義一個隱含規則。一個模式規則就好像一個一般的規則,只是在規則中目標的定義需要%字元,%字元表示一個或多個任意字元。在依賴目標中可以使用%,只是以來目標的%取值取決於它的目標。

%的展開發生在變數和函數的展開之後,變數和函數的展開發生在make載入Makefile時,模式規則的%發生在執行時。

%.c表示以.c結束的檔名(檔名的長度至少爲 3)

s.%.c表示以s.開頭和及.c結束的檔名(檔名的長度至少爲5)

  • 自動化變數
變數 說明
$@ 表示規則中的目標檔案集
$% 僅當目標是函數庫檔案時,表示規則中的目標成員名
$< 依賴目標的第一個目標名字
$? 所有比目標新的依賴目標的幾個
$^ 所有的依賴目標的集合(去重)
$+ 所有的以來目標的集合(不去重)
$* 表示目標模式中%及其之前的部分

後綴規則

後綴規則是一個比較老式的定義隱含規則的方法。後綴規則有兩種,雙後綴和單後綴。

隱含規則搜尋演算法