4)變量的引入
變量的引入和應用:
CC=gcc
HD=-I headers
SC=-c $<
OBJ=-o $@
bin/st_work : obj/main.o obj/st_work.o obj/fun.o
gcc $^ -o $@ (指令一定要用以Tab開頭)
obj/st_work.o : sources/st_work.c
$(CC) $(HD) $(SC) $(OBJ)
obj/main.o : sources/main.c
obj/fun.o : sources/fun.c
clean:
rm -f bin/st_work file_o/*.o
可以看到,依賴關系由上到下。
More:
(1)如此定義變量後,
objects = main.o,
foo = $(bar)
使用$(object)來代替變量的值,用“$$”來表示$。
(2)變量替換
其格式是“$(var:a=b)”或是“${var:a=b}”,其意思是,把變量“var”中所有以“a”字串“結尾”的“a”替換成“b”字串。這裡的“結尾”意思是“空格”或是“結束符”。
foo := a.o b.o c.o
bar := $(foo:.o=.c)
(3)變量可以嵌套
$($(x))
(4)可以使用“+=”操作符給變量追加值。
(5)當make嵌套調用時,上層Makefile中定義的變量會以系統環境變量的方式傳遞到下層的Makefile中。這裡的系統環境變量與本makefile中定義的變量的關系有點類似于全局變量與局部變量的關系。預設情況下,隻有通過指令行設定的變量會被傳遞。而定義在檔案中的變量,如果要向下層Makefile傳遞,則需要使用exprot關鍵字來聲明。
5)資訊顯示
在執行make時,會把所有這些資訊都輸出來。
在指令前面加個@,就不會把相關資訊輸出螢幕了。
6)函數的使用
函數調用後,函數的傳回值可以當做變量來使用。
調用格式如下所示: $(<function> <arguments>;)
函數調用以“$”開頭,以圓括号或花括号把函數名和參數括起。參數間以逗号“,”分隔,而函數名和參數之間以“空格”分隔。參數可以使用變量。
bar:= $(subst $(space),$(comma),$(foo))
上面的函數subst是把第三個參數中包含第一個參數中的字串替換成第二個參數中的字串。
7)語句的使用
$(if <condition>;,<then-part>;)
$(if <condition>;,<then-part>;,<else-part>;)
make支援三各通配符:“*”,“?”和“[...]”。波浪号“~”字元在檔案名中也有比較特殊的用途。如果是“~/test”,這就表示目前使用者的$HOME目錄下的test目錄。而“~hchen/test”則表示使用者hchen的宿主目錄下的test目錄
5、其他注意點
1)在大多數時候,由于源檔案太多,編譯生成的中間目标檔案太多,而在連結時需要明顯地指出中間目标檔案名,這對于編譯很不友善,是以,通常要給中間目标檔案打個包,在Windows 下這種包叫“庫檔案”(Library File),也就是 .lib 檔案,在UNIX 下,是Archive File,也就是 .a 檔案。
編譯階段,主要解決文法問題,如函數,變量等聲明是否正确,而連結階段,因為要生成可執行檔案了,要明确具體的位址關系,及尋找真實的定義等。
2)将長行用 “\” 分開便于閱讀。
3)和目标沒有依賴關系的規則不會被處理,除非指定make 處理(如make clean)。
4)将源檔案分門别類地放置時,編譯時要進行尋找。通過VPATH實作。
如果沒有指明這個變量,make 隻會在目前的目錄中去找尋依賴檔案和目标檔案。如果定義了這個變量,那麼,make就會在當目前目錄找不到的情況下,到所指定的目錄中去找尋檔案了。
VPATH = src:../headers
多個目錄使用:分開。
另外一個vpath,不是變量,使用方法如下:
它可以指定不同的檔案在不同的搜尋目錄中。使用方法有三種:
(1)vpath <pattern> <directories>。為符合模式<pattern>的檔案指定搜尋目錄<directories>。
(2)vpath <pattern>。清除符合模式<pattern>的檔案的搜尋目錄。
(3)vpath。清除所有已被設定好了的檔案搜尋目錄。
<pattern>需要包含“%”字元。“%”的意思是比對零或若幹字元,例如,“%.h”表示所有以“.h”結尾的檔案。<pattern>指定了要搜尋的檔案集,而<directories>則指定了<pattern>的檔案集的搜尋的目錄。例如:
vpath %.h ../headers
該語句表示,要求make 在“../headers”目錄下搜尋所有以“.h”結尾的檔案。
5)有些情況下,則規則失效,沒有依賴檔案,檔案clean指令永遠不會執行;為避免這個問題,可使用".PHONY"指明該目标。如:
.PHONY : clean
這樣,在make clean是會無視clean是否存在,直接執行其指令。
與上面等效的另外一個表達:
clean: FORCE
rm $(objects)
FORCE:
6)此外,還有很少使用的雙冒号規則。
7)使用include關鍵字可以把别的Makefile包含進來。