像寫程式一樣,make規則裡面的組成可以有動態的值,這時就需要用變數來 設值來取代與轉換以及日後維護。另外還有就是有時字太多了,打字打到 可能會出錯,這樣除錯起Makefile很不好除錯,用變數代換值可以減少一 些打字錯誤。變數也有一些規定,
字母大小有差。
不要用字母數字底線以外的字元。可以有空格在前面後面。 (像shell script就不行有空格在變數前後。Var = value跟 Var=value是不一樣的)。
使用變數用$(VAR)或者${VAR}都可以。
如果要用$,請多加一個$變成$$,在Shell Command會用到Shell 變數此時就要加$。
Example 5-2. 設objects
objects = program.o foo.o utils.o program : $(objects) cc -o program $(objects) |
變數代換有兩種很重要的不同代換。遞迴的變數代換 (recursively expand)只要變數的值又是另一個變數值時, 就會一直代換下去。簡單的變數代換(simple expand)只代換一次變數的值。
變數代換
var = value
var := value
Example 5-3. 例子
foo = $(bar) bar = $(ugh) ugh = Huh? all: echo $(foo) |
遞迴的方法有個壞處,不能夠加東西上去,例如
CFLAGS = -Isrc/include CFLAGS = $(CFLAGS) -O |
CFLAGS += -O |
wildcard在變數中可以展成所有的意義,但是在Makefile中使用要小心 例如
OBJECTS = *.o foo: $(OBJECTS) cc -o foo $(OBJECTS) |
所以如果要傳Shell的變數給Shell就不要讓make對$這個符號做解釋, 所以要多加$。例如
linuxsubdirs: dummy set -e; for i in $(Subdirs); do $(MAKE) -C $$i; done |
傳變數給Shell可以用
export var1 var2 var3.... |
VAR := $(shell shell_command) |
例如
prog : CFLAGS = -g prog : prog.o foo.o bar.o |
目標可以是檔名或者是一個代表動作的識別符號,如果不是檔名的Target叫 phony target。make根據指定的target來做相關動作。
要完成一個目標前會先檢查他所需要的檔案或要先做的phnoy target,即 相依性檔案或先決條件目標(dependency or prerequiste) 如果要的相依或先決目標不存在,則make會失敗。如果這裡的先決目標是 phony target則PHONY TARGET每次都會被執行。
如果你在shell prompt只下make命令而已,第一個rule永遠被執行。 這叫default goal。如果你有指定target名字,例如make clean,則會 去執行這個target的動作,以上面例子看就是會執行 rm *.o *~ 這個動作。
有些phony目標是GNU建議的,不見得一定要有啦只是建議目標。例如
all :內定的編譯動作 install :安裝binary檔的動作 clean :清除obj檔的動作 dist :產生configure的動作 distclean :清除configure所產生的檔 |
有些目標名稱已經有特別規定了,例如
一些內定目標
在這個後面的target無條件執行。因為例如
clean: rm *.o |
make有一些內定方法編譯特別副檔名,這些副檔名規則的副檔名 (名單)list,是在SUFFIXS這個變數裡, 可能有.c .o .cpp 等等。 用
.SUFFIXS: |
.SUFFIXS: .sgml .hack |
這裡面的target執行時 命令(command)將不會印出來
把所有變數告訴後來sub shell的子程序
命令就是要完成一個目標所要做的動作, 有幾個比較重要的規定要清楚
command 前面一定要是個TAB鍵。不可以用空白鍵。
每一行的命令其實都是喚起一個sub shell來執行命令,做完了, 這個sub shell就沒有了。
所以更改過的變化不能傳給下一行命令。如果要把執行結果傳給下一 行必須寫在同一行裡。例如
cd editor $(MAKE) all |
cd editor; \ $(MAKE) all |
要把錯誤掠過不看在命令前加個- 要不秀出命令在螢幕上加個@,例如前面例子裡的clean這個target。
喚起的sub shell要用什麼shell,是定義在SHELL這個變數裡。