跟我一起寫 Makefile (二 總述)陳皓

2021-09-19 03:40:04 字數 3750 閱讀 4757

makefile裡主要包含了五個東西:顯式規則隱晦規則變數定義檔案指示注釋

1、顯式規則。顯式規則說明了,如何生成乙個或多的的目標檔案。這是由makefile的書寫者明顯指出,要生成的檔案,檔案的依賴檔案,生成的命令。

2、隱晦規則。由於我們的make有自動推導的功能,所以隱晦的規則可以讓我們比較粗糙地簡略地書寫makefile,這是由make所支援的。

3、變數的定義。在makefile中我們要定義一系列的變數,變數一般都是字串,這個有點像c語言中的巨集,當makefile被執行時,其中的變數都會被擴充套件到相應的引用位置上。

4、檔案指示。其包括了三個部分,

(1)乙個是在乙個makefile中引用另乙個makefile,就像c語言中的include一樣

(2)另乙個是指根據某些情況指定makefile中的有效部分,就像c語言中的預編譯#if一樣

(3)還有就是定義乙個多行的命令。有關這一部分的內容,我會在後續的部分中講述。

5、注釋。makefile中只有行注釋,和unix的shell指令碼一樣,其注釋是用「#」字元,這個就像c/c++中的「//」一樣。如果你要在你的makefile中使用「#」字元,可以用反斜框進行轉義,如:「/#」。

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

預設的情況下,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使用include關鍵字可以把別的makefile包含進來,這很像c語言的#include,被包含的檔案會原模原樣的放在當前檔案的包含位置。include的語法是:

include

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,其作用和這乙個是一樣的。

如果你的當前環境中定義了環境變數makefiles,那麼,make會把這個變數中的值做乙個類似於include的動作。這個變數中的值是其它的makefile,用空格分隔。只是,它和include不同的是,從這個環境變數中引入的makefile的「目標」不會起作用,如果環境變數中定義的檔案發現錯誤,make也會不理。

環境變數和自定義變數 -》類似於「全域性變數」和「區域性變數」

建立個環境變數cwr

export cwr=666
通過env來檢視所有環境變數

makefile中輸出該變數

cwr:

@echo $(cwr)

@ 作用關閉命令回顯

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make cwr

666

在makefile中定義該變數

cwr = 233

cwr:

@echo $(cwr)

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make cwr

233

不過我看很多廠商在編譯系統映象前,都會先source 一下廠商寫的環境變數指令碼。估計也是為了讓每個模組共通的部分集中在環境變數中,使得模組的makefile看起來更簡潔更容易閱讀。

但是在這裡我還是建議不要使用這個環境變數,因為只要這個變數一被定義,那麼當你使用make時,所有的makefile都會受到它的影響,這絕不是你想看到的。在這裡提這個事,只是為了告訴大家,也許有時候你的makefile出現了怪事,那麼你可以看看當前環境中有沒有定義這個變數。

gnu的make工作時的執行步驟入下:(想來其它的make也是類似)

1、讀入所有的makefile。

2、讀入被include的其它makefile。

3、初始化檔案中的變數。

4、推導隱晦規則,並分析所有規則。

5、為所有的目標檔案建立依賴關係鏈。

6、根據依賴關係,決定哪些目標要重新生成。

7、執行生成命令。

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

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

跟我一起寫 Makefile(二)

三 make是如何工作的 在預設的方式下,也就是我們只輸入make命令。那麼,1 make會在當前目錄下找名字叫 makefile 或 makefile 的檔案。2 如果找到,它會找檔案中的第乙個目標檔案 target 在上面的例子中,他會找到 edit 這個檔案,並把這個檔案作為最終的目標檔案。3...

跟我一起寫 Makefile(二)

三 make是如何工作的 在預設的方式下,也就是我們只輸入make命令。那麼,1 make會在當前目錄下找名字叫 makefile 或 makefile 的檔案。2 如果找到,它會找檔案中的第乙個目標檔案 target 在上面的例子中,他會找到 edit 這個檔案,並把這個檔案作為最終的目標檔案。3...

跟我一起寫 Makefile(二)

三 make是如何工作的 在預設的方式下,也就是我們只輸入make命令。那麼,1 make會在當前目錄下找名字叫 makefile 或 makefile 的檔案。2 如果找到,它會找檔案中的第乙個目標檔案 target 在上面的例子中,他會找到 edit 這個檔案,並把這個檔案作為最終的目標檔案。3...