make機制的運行環境需要一個命令行程序make和一個文本文件Makefile。
make命令執行後有3個退出碼:
|
make的使用格式是:
make [options] [target] ...
options爲make工具的參數選項,target爲makefile中指定的目標。
make工具的參數選項
選項 |
含義 |
-f filename |
顯式地指定文件作爲Makefile |
-C dirname |
指定make在開始運行後的工作目錄爲dirname |
-e |
不允許在Makefile中替換環境變量的賦值 |
-k |
執行命令出錯時,放棄當前目標,繼續維護其他目標 |
-n |
按實際運行時的執行順序模擬執行命令(包括用@開頭的命令),沒有實際執行效果,僅僅用於顯示執行過程 |
-p |
顯示makefile中所有的變量和內部規則 |
-r |
忽略內部規則 |
-s |
執行但不顯示命令 |
-S |
如果執行命令出錯就退出 |
-t |
修改每個目標文件的創建日期 |
-I |
忽略運行make中執行命令的錯誤 |
-V |
顯示make的版本號 |
make操作管理Makefile文件的規則
|
在makefile中,目標名稱的指定通常有以下慣例:
|
Makefile的書寫規則
Makefile的書寫規則包含兩個部分,一個是依賴關係,一個是生成目標的方法。
Makefile中只有一個最終目標,第一條規則中的第一個目標將被確立爲最終的目標。
Makefile裏主要包含了5方面的內容:顯式規則、隱式規則、變量定義、文件指示和註釋。
|
Makefile的基本語法規則
Makefile的語法格式如下:
targets : prerequisites
command
...
或者是:
targets : prerequisites ; command
command
...
-
targets是目標文件名,多個文件以空格分開,可以使用通配符。一般說來,Makefile的目標是一個文件,但也有可能是多個文件。
-
prerequisites是目標所依賴的文件(或依賴目標)。
-
command是命令行,如果它不與”targets:prerequisites”在一行,那麼必須以Tab鍵開頭,如果和prerequisites在同一行,那麼可以用分號作爲分隔。如果命令太長,可以使用反斜槓“\”作爲換行符。make對一行中有多少個字符沒有限制。
對於Makefile文件: all : main.c foo1.c foo2.c foo3.c gcc main.c foo1.c foo2.c foo3.c -o all all是Makefile時最終目標,main.c,foo1.c,foo2.c,foo3.c是目標所依賴的源文件,而只有一個命令“gcc main.c foo1.c foo2.c foo3.c -o all”是生成目標的方法:
|
在規則中使用通配符
make支持3種通配符:“*”,“?”,“[...]”。
“~”字符在文件名中有特殊用途:比如“~/test”表示當前用戶的$HOME目錄下的test目錄;“~zhangfan/test”則表示用戶zhangfan的宿主目錄下的test目錄。
通配符代替了一系列的文件,如”*.c”表示了所有後綴名爲.c的文件。如果文件名中含有通配符,如“*”,那麼可以用轉義字符斜槓”\”,如“\*”來表示真實的”*“字符,而不是任意長度的字符串。
可以使用一個特殊的標記“.PHONY”來顯式地指明一個目標是僞目標,向make說明,不管是否有這個文件,這個目標都是僞目標:
.PHONY : clean
只要有這個聲明,不管是否有“clean”文件,要運行“clean”這個目標,只要在命令提示符下輸入命令“make clean”即可。於是整個過程可以這樣寫,例如:
.PHONY : clean
clean :
rm all main.o kbd.o command.o \
insert.o search.o files.o
自動生成依賴關係
可以使用GNU的C/C++編譯器的“-MM”參數選項,使其自動尋找源文件中包含的頭文件,並生成一個依賴關係。例如main.c文件中有defs.h頭文件,那麼:
gcc -MM main.c
其輸出是:
main.o : main.c defs.h
變量
變量在聲明時需要給予初值,而在使用時,需要在變量名前加上“$”符號,但最好用小括號“()”或是花括號”{}”把變量給引用起來。如果使用真實的”$”字符,那麼需要用”$$”來表示。
下面Makefile等同:
objects=program.o foo.o utils.o
program:$(objects)
cc -o program $(objects)
$(objects):defs.h
等同於:
objects=program.o foo.o utils.o
program:program.o foo.o utils.o
cc -o program program.o foo.o utils.o
program.o foo.o utils.o:defs.h
賦值變量
1、使用“:=”操作符,使得前面的變量不能使用後面的變量,只能使用前面已定義好了的變量。
2、使用”?=”操作符:例如foo ?= bar 如果foo沒有被定義過,那麼變量foo的值就是“bar”,否則此語句什麼也不做,這段代碼等同於:
ifeq($(origin foo),undefined)
foo=bar;
endif
3、使用“+=”操作符,可以追加值,
objects=main.o foo.o bar.o
objects+=another.o
等同於
objects=main.o foo.o bar.o
objects:=$(objects) another.o
define關鍵字
使用define定義的命令變量中沒有以“Tab”鍵開頭。
define two-lines
echo foo
echo $(bar)
endef
這段代碼將變量two-lines定義爲兩條命令echo foo和echo $(bar)。
override指示符
有的變量時通過make的命令行參數進行設置的,那麼Makefile將忽略這個變量的賦值。如果想在Makefile中設置這類參數的值,那麼可以使用“override”指示符。
override =
override :=
override +=
在define關鍵字中也同樣可以使用override指示符:
override define foo
bar
endef
目標變量和模式變量
1、目標變量
:
:override
爲目標序列,可以是各種賦值表達式,如”=”、”:=“,”+=“,”?=”。第二個語法針對於make命令行參數帶入的變量,或是系統環境變量。
prog : CFLAGS=-g
prog : prog.o foo.o bar.o
$(CC) $(CFLAGS) prog.o foo.o bar.o
prog.o : prog.c
$(CC) $(CFLAGS) prog.c
foo.o : foo.c
$(CC) $(CFLAGS) foo.c
bar.o : bar.c
$(CC) $(CFLAGS) bar.c
等同於
prog : prog.c foo.c bar.o
gcc -g prog.o foo.o bar.o
prog.o : prog.c
gcc -g prog.c
foo.o : foo.c
gcc -g foo.c
bar.o : bar.c
gcc -g bar.c
2、模式變量
可以給定一種“模式”,把變量定義在符合這個模式的所有目標中。
:
:override
是模式序列,可以是多種模式,override同樣是針對系統環境傳入的變量或是make命令行指定的變量。
make的模式變量一般是至少含有一個“%”的,所以,可以以如下方式給所有以”.o”結尾的目標定義目標模式變量:
%.o : CFLAGS=-o