Makefile 學習 2 - 基於若干 Blog 的彙總

基於若干 Blog 彙總的 makefile 教程spa

陳皓 https://blog.csdn.net/haoel/article/details/2886操作系統

Makefile 進階

1. Makefile 中的內容

  1. 顯式規則。顯式規則說明了,如何生成一個或多的的目標文件。這是由Makefile的書寫者明顯指出,要生成的文件,文件的依賴文件,生成的命令。
  2. 隱晦規則。因爲咱們的make有自動推導的功能,因此隱晦的規則可讓咱們比較粗糙地簡略地書寫Makefile,這是由make所支持的。
  3. 變量的定義。在Makefile中咱們要定義一系列的變量,變量通常都是字符串,這個有點你C語言中的宏,當Makefile被執行時,其中的變量都會被擴展到相應的引用位置上。
  4. 文件指示。其包括了三個部分,一個是在一個Makefile中引用另外一個Makefile,就像C語言中的include同樣;另外一個是指根據某些狀況指定Makefile中的有效部分,就像C語言中的預編譯#if同樣;還有就是定義一個多行的命令。有關這一部分的內容,我會在後續的部分中講述。
  5. 註釋。Makefile中只有行註釋,和UNIX的Shell腳本同樣,其註釋是用「#」字符,這個就像C/C++中的「//」同樣。若是你要在你的Makefile中使用「#」字符,能夠用反斜框進行轉義,如:「#」。

2. Makefile 文件名

默認的狀況下,make命令會在當前目錄下按順序找尋文件名爲「GNUmakefile」、「makefile」、「Makefile」的文件,找到了解釋這個文件。在這三個文件名中,最好使用「Makefile」這個文件名,由於,這個文件名第一個字符爲大寫,這樣有一種顯目的感受。最好不要用「GNUmakefile」,這個文件是GNU的make識別的。有另一些make只對全小寫的「makefile」文件名敏感,可是基本上來講,大多數的make都持「makefile」和「Makefile」這兩種默認文件名。.net

固然,你可使用別的文件名來書寫Makefile,好比:「Make.Linux」,「Make.Solaris」,「Make.AIX」等,若是要指定特定的Makefile,你可使用make的「-f」和「--file」參數,如:make -f Make.Linux或make --file Make.AIX。code

3. 引用別的 Makefile

在Makefile使用include關鍵字能夠把別的Makefile包含進來,這很像C語言的 #include,被包含的文件會原模原樣的放在當前文件的包含位置。include的語法是:blog

include<filename>
    filename能夠是當前操做系統Shell的文件模式(能夠保含路徑和通配符)

在include前面能夠有一些空字符,可是毫不能是[Tab]鍵開始。include和能夠用一個或多個空格隔開。舉個例子,你有這樣幾個Makefile:a.mk、b.mk、c.mk,還有一個文件叫foo.make,以及一個變量$(bar),其包含了e.mk和f.mk,那麼,下面的語句:教程

include foo.make *.mk $(bar)

等價於:字符串

include foo.make a.mk b.mk c.mk e.mk f.mk

make命令開始時,會把找尋include所指出的其它Makefile,並把其內容安置在當前的位置。就好像C/C++的#include指令同樣。若是文件都沒有指定絕對路徑或是相對路徑的話,make會在當前目錄下首先尋找,若是當前目錄下沒有找到,那麼,make還會在下面的幾個目錄下找:自動化

1.若是make執行時,有「-I」或「--include-dir」參數,那麼make就會在這個參數所指定的目錄下去尋找。
2.若是目錄/include(通常是:/usr/local/bin或/usr/include)存在的話,make也會去找。編譯

若是有文件沒有找到的話,make會生成一條警告信息,但不會立刻出現致命錯誤。它會繼續載入其它的文件,一旦完成makefile的讀取,make會再重試這些沒有找到,或是不能讀取的文件,若是仍是不行,make纔會出現一條致命信息。若是你想讓make不理那些沒法讀取的文件,而繼續執行,你能夠在include前加一個減號「-」。如:
-include
其表示,不管include過程當中出現什麼錯誤,都不要報錯繼續執行。和其它版本make兼容的相關命令是sinclude,其做用和這一個是同樣的。test

4. Makefile 的工做方式

stage1:

  1. 讀入全部的Makefile。
  2. 讀入被include的其它Makefile。
  3. 初始化文件中的變量。
  4. 推導隱晦規則,並分析全部規則。
  5. 爲全部的目標文件建立依賴關係鏈。

stage2:

  1. 根據依賴關係,決定哪些目標要從新生成。
  2. 執行生成命令。

第一個階段中,若是定義的變量被使用了,那麼,make會把其展開在使用的位置。但make並不會徹底立刻展開,make使用的是拖延戰術,若是變量出如今依賴關係的規則中,那麼僅當這條依賴被決定要使用了,變量纔會在其內部展開。

5. Makefile 中的通配符

~
波浪號(「~」)字符在文件名中也有比較特殊的用途。若是是「~/test」,這就表示當前用戶的$HOME目錄下的test目錄。而「~hchen/test」則表示用戶hchen的宿主目錄下的test目錄。(這些都是Unix下的小知識了,make也支持)而在Windows或是MS-DOS下,用戶沒有宿主目錄,那麼波浪號所指的目錄則根據環境變量「HOME」而定。


通配符代替了你一系列的文件,如「.c」表示因此後綴爲c的文件。一個須要咱們注意的是,若是咱們的文件名中有通配符,如:「」,那麼能夠用轉義字符「\」,如「」來表示真實的「」字符,而不是任意長度的字符串。

clean:
    rm -f *.o

上面這個例子我不很少說了,這是操做系統Shell所支持的通配符。這是在命令中的通配符。

print: *.c
    lpr -p $?
    touch print

上面這個例子說明了通配符也能夠在咱們的規則中,目標print依賴於全部的[.c]文件。其中的「$?」是一個自動化變量,我會在後面給你講述。

objects = *.o

上面這個例子,表示了,通符一樣能夠用在變量中。並非說 [.o] 會展開,不!objects的值就是「.o」。Makefile中的變量其實就是C/C++中的宏。若是你要讓通配符在變量中展開,也就是讓objects的值是全部[.o]的文件名的集合,那麼,你能夠這樣:

objects := $(wildcard *.o)

這種用法由關鍵字「wildcard」指出,關於Makefile的關鍵字,咱們將在後面討論。

6. 文件搜尋

在一些大的工程中,有大量的源文件,咱們一般的作法是把這許多的源文件分類,並存放在不一樣的目錄中。因此,當make須要去找尋文件的依賴關係時,你能夠在文件前加上路徑,但最好的方法是把一個路徑告訴make,讓make在自動去找。

Makefile文件中的特殊變量「VPATH」就是完成這個功能的,若是沒有指明這個變量,make只會在當前的目錄中去找尋依賴文件和目標文件。若是定義了這個變量,那麼,make就會在噹噹前目錄找不到的狀況下,到所指定的目錄中去找尋文件了。

VPATH = src:../headers

上面的的定義指定兩個目錄,「src」和「../headers」,make會按照這個順序進行搜索。目錄由「冒號」分隔。(固然,當前目錄永遠是最高優先搜索的地方)

另外一個設置文件搜索路徑的方法是使用make的「vpath」關鍵字(注意,它是全小寫的),這不是變量,這是一個make的關鍵字,這和上面提到的那個VPATH變量很相似,可是它更爲靈活。它能夠指定不一樣的文件在不一樣的搜索目錄中。這是一個很靈活的功能。它的使用方法有三種:

  1. vpath < pattern> < directories> 爲符合模式< pattern>的文件指定搜索目錄。
  2. vpath < pattern> 清除符合模式< pattern>的文件的搜索目錄。
  3. vpath 清除全部已被設置好了的文件搜索目錄。

vapth使用方法中的< pattern>須要包含「%」字符。「%」的意思是匹配零或若干字符,例如,「%.h」表示全部以「.h」結尾的文件。< pattern>指定了要搜索的文件集,而< directories>則指定了的文件集的搜索的目錄。例如:

vpath %.h ../headers

該語句表示,要求make在「../headers」目錄下搜索全部以「.h」結尾的文件。(若是某文件在當前目錄沒有找到的話)

咱們能夠連續地使用vpath語句,以指定不一樣搜索策略。若是連續的vpath語句中出現了相同的< pattern>,或是被重複了的< pattern>,那麼,make會按照vpath語句的前後順序來執行搜索。如:

vpath %.c foo
   vpath %   blish
   vpath %.c bar

其表示「.c」結尾的文件,先在「foo」目錄,而後是「blish」,最後是「bar」目錄。

vpath %.c foo:bar
   vpath %   blish

而上面的語句則表示「.c」結尾的文件,先在「foo」目錄,而後是「bar」目錄,最後纔是「blish」目錄。

相關文章
相關標籤/搜索