Makefile的規則
target ... : prerequisites ...command
...
...
target也就是一個目標文件,可以是Object File,也可以是執行文件。還可以是一個標籤(Label),對於標籤這種特性,在後續的“僞目標”章節中會有敘述。
prerequisites就是,要生成那個target所需要的文件或是目標。
command也就是make需要執行的命令。(任意的Shell命令)
這是一個文件的依賴關係,也就是說,target這一個或多個的目標文件依賴於prerequisites中的文件,其生成規則定義在command中。說白一點就是說,prerequisites中如果有一個以上的文件比target文件要新的話,或者target不存在的話,那麼,make就會執行後續定義的命令command所定義的命令就會被執行(command一定要以一個Tab鍵作爲開頭)。這就是Makefile的規則。也就是Makefile中最核心的內容。
說明:clean不是一個文件,它只不過是一個動作名字,有點像C語言中的lable一樣,其冒號後什麼也沒有,那麼,make就不會自動去找文件的依賴性,也就不會自動執行其後所定義的命令。要執行其後的命令,就要在make命令後明顯得指出這個lable的名字。這樣的方法非常有用,我們可以在一個makefile中定義不用的編譯或是和編譯無關的命令,比如程序的打包,程序的備份,等等。
----------------------------------------------------------------------------------------------------
1. 寫一個Makefile來告訴make命令如何編譯和鏈接這幾個文件。我們的規則是:
1)如果這個工程沒有編譯過,那麼我們的所有C文件都要編譯並被鏈接。2)如果這個工程的某幾個C文件被修改,那麼我們只編譯被修改的C文件,並鏈接目標程序。
3)如果這個工程的頭文件被改變了,那麼我們需要編譯引用了這幾個頭文件的C文件,並鏈接目標程序。
目標文件在編譯的過程中,如果出現錯誤,比如最後被依賴的文件找不到,那麼make就會直接退出,並報錯,而對於所定義的命令的錯誤,或是編譯不成功,make根本不理。make只管文件的依賴性,即,如果在我找了依賴關係之後,冒號後面的文件還是不在,那麼對不起,我就不工作啦。
2. object 變量,使用變量的形式,表示目標文件:objects = main.o kbd.o command.o display.o,然後很方便地在我們的makefile中以“$(objects)”的方式來使用這個變量;
3. “隱晦規則”和“僞目標文件”
1> “隱晦規則”:GNU的make 非常強大,可以通過目標 .o 文件推導出相應的 .c 及編譯命令等;
2> “僞目標文件”:
.PHONY : clean
clean :-rm edit $(objects)
.PHONY意思表示clean是一個“僞目標”。而在rm命令前面加了一個小減號的意思就是,也許某些文件出現問題,但不要管,繼續做後面的事;加上 .PHONY 的目的是爲了避免和文件重名的這種情況;
.PHONY的實際使用範例:
1> 如果你的Makefile需要一口氣生成若干個可執行文件,但你只想簡單地敲一個make完事,並且,所有的目標文件都寫在一個Makefile中,那麼你可以使用“僞目標”這個特性:
all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o
2> 目標也可以成爲依賴。所以,僞目標同樣也可成爲依賴。看下面的例子:
.PHONY: cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm program
cleanobj :
rm *.o
cleandiff :
rm *.diff
“make clean”將清除所有要被清除的文件。“cleanobj”和“cleandiff”這兩個僞目標有點像“子程序”的意思。我們可以輸入“make cleanall”和“make cleanobj”和“make cleandiff”命令來達到清除不同種類文件的目的。
4. 引用其它的Makefile
在Makefile使用include關鍵字可以把別的Makefile包含進來,這很像C語言的#include,被包含的文件會原模原樣的放在當前文件的包含位置。
include foo.make *.mk
等價於:
include foo.make a.mk b.mk
查找Makefile路徑一般是在當前的目錄下,或者make執行的時候,“-I”或“--include-dir”參數;
5. 文件搜尋
在一些大的工程中,有大量的源文件,我們通常的做法是把這許多的源文件分類,並存放在不同的目錄中。所以,當make需要去找尋文件的依賴關係時,你可以在文件前加上路徑,但最好的方法是把一個路徑告訴make,讓make在自動去找;
1、 首先搜索的目錄是當前目錄;
2、 VPATH = src:../headers 冒號分離不同的文件目錄,此例子先後在 src 和 ../headers 目錄下進行查詢;
3、 make的“vpath”關鍵字(注意,它是全小寫的);
1> vpath <pattern>; <directories>;
爲符合模式<pattern>;的文件指定搜索目錄<directories>。
例子:vpath %.h ../headers 表示在目錄 ../headers 下查找 .h 頭文件;
2> vpath <pattern>;
清除符合模式<pattern>;的文件的搜索目錄。
3> vpath
清除所有已被設置好了的文件搜索目錄。