1. 程式人生 > >make之makefile 二 總述

make之makefile 二 總述

此文章是我從另一篇文章中提取出來的,分類出來,便於初學者學習檢視,該文章地址:https://www.cnblogs.com/mfryf/p/3305778.html

一、Makefile裡有什麼?

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中使用“#”字元,能夠用反斜框進行轉義,如:“/#”。

最後,還值得一提的是,在Makefile中的命令,必須要以[Tab]鍵開始

二、Makefile的檔名稱

預設的情況下,make命令會在當前資料夾下按順序找尋檔名稱為“GNUmakefile”、“makefile”、“Makefile”的檔案,找到了解釋這個檔案。在這三個檔名稱中,最好使用“Makefile”這個檔名稱,由於,這個檔名稱第一個字元為大寫,這樣有一種顯目的感覺。最好不要用“GNUmakefile”,這個檔案是GNU的make識別的。有另外一些make僅僅對全小寫的“makefile”檔名稱敏感,可是基本上來說,大多數的make都支援“makefile”和“Makefile”這兩種預設檔名稱。

當然,你能夠使用別的檔名稱來書寫Makefile,比方:“Make.Linux”,“Make.Solaris”,“Make.AIX”等,假設要指定特定的Makefile,你能夠使用make的“-f”和“--file”引數,如:make -f Make.Linux或make --file Make.AIX。


三、引用其他的Makefile

在Makefile使用includekeyword能夠把別的Makefile包括進來,這非常像C語言的#include,被包括的檔案會原模原樣的放在當前檔案的包括位置。include的語法是:

include <filename>

filename能夠是當前作業系統Shell的檔案模式(能夠保含路徑和萬用字元)

在include前面能夠有一些空字元,可是絕不能是[Tab]鍵開始。include和<filename>能夠用一個或多個空格隔開。舉個樣例,你有這樣幾個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、假設資料夾<prefix>/include(通常是:/usr/local/bin或/usr/include)存在的話,make也會去找。

假設有檔案沒有找到的話,make會生成一條警告資訊,但不會立即出現致命錯誤。它會繼續載入其他的檔案,一旦完成makefile的讀取,make會再重試這些沒有找到,或是不能讀取的檔案,假設還是不行,make才會出現一條致命資訊。假設你想讓make不理那些無法讀取的檔案,而繼續執行,你能夠在include前加一個減號“-”。如:

-include <filename>
其表示,無論include過程中出現什麼錯誤,都不要報錯繼續執行。和其他版本號make相容的相關命令是sinclude,其作用和這一個是一樣的。


四、環境變數 MAKEFILES 

假設你的當前環境中定義了環境變數MAKEFILES,那麼,make會把這個變數中的值做一個相似於include的動作。這個變數中的值是其他的Makefile,用空格分隔。僅僅是,它和include不同的是,從這個環境變中引入的Makefile的“目標”不會起作用,假設環境變數中定義的檔案發現錯誤,make也會不理。(這段話我不是很明白????)

可是在這裡我還是建議不要使用這個環境變數,由於僅僅要這個變數一被定義,那麼當你使用make時,全部的Makefile都會受到它的影響,這絕不是你想看到的。在這裡提這個事,僅僅是為了告訴大家,或許有時候你的Makefile出現了怪事,那麼你能夠看看當前環境中有未定義這個變數。


五、make的工作方式

GNU的make工作時的執行步驟入下:(想來其他的make也是相似)

1、讀入全部的Makefile。
2、讀入被include的其他Makefile。
3、初始化檔案裡的變數。
4、推導隱晦規則,並分析全部規則。
5、為全部的目標檔案建立依賴關係鏈。
6、依據依賴關係,決定哪些目標要又一次生成。
7、執行生成命令。

1-5步為第一個階段,6-7為第二個階段。第一個階段中,假設定義的變數被使用了,那麼,make會把其展開在使用的位置。但make並不會全然立即展開,make使用的是遲延戰術,假設變量出現在依賴關係的規則中,那麼僅當這條依賴被決定要使用了,變數才會在其內部展開。

當然,這個工作方式你不一定要清晰,可是知道這個方式你也會對make更為熟悉。有了這個基礎,後續部分也就easy看懂了。