編寫makefile文件規則

make機制的運行環境需要一個命令行程序make和一個文本文件Makefile

make命令執行後有3個退出碼:

  • 表示成功執行。

  • 如果make運行時出現任何錯誤,則返回1.

  • 如果使用了make的“-q”選項,並且make使得一些目標不需要更新,那麼返回2.


make的使用格式是:

make [options] [target] ...

optionsmake工具的參數選項,targetmakefile中指定的目標。

make工具的參數選項

選項

含義

-f filename

顯式地指定文件作爲Makefile

-C dirname

指定make在開始運行後的工作目錄爲dirname

-e

不允許在Makefile中替換環境變量的賦值

-k

執行命令出錯時,放棄當前目標,繼續維護其他目標

-n

按實際運行時的執行順序模擬執行命令(包括用@開頭的命令),沒有實際執行效果,僅僅用於顯示執行過程

-p

顯示makefile中所有的變量和內部規則

-r

忽略內部規則

-s

執行但不顯示命令

-S

如果執行命令出錯就退出

-t

修改每個目標文件的創建日期

-I

忽略運行make中執行命令的錯誤

-V

顯示make的版本號

make操作管理Makefile文件的規則

  • 如果這個工程沒有編譯過,那麼所有C文件都需要被編譯和鏈接

  • 如果這個工程中的某幾個C文件被修改,則只需編譯被修改過的C文件,並連接目標程序

  • 如果這個工程的頭文件被修改了,則需要編譯引用了這幾個頭文件的C文件,並鏈接目標程序

makefile中,目標名稱的指定通常有以下慣例:

  • all:表示編譯所有的內容,時執行make時默認的最終的目標。

  • clean:表示清除所有目標文件。

  • distclean:表示清除所有的內容。

  • install:表示進行安裝的內容。

Makefile的書寫規則

Makefile的書寫規則包含兩個部分,一個是依賴關係,一個是生成目標的方法。

Makefile中只有一個最終目標,第一條規則中的第一個目標將被確立爲最終的目標。

Makefile裏主要包含了5方面的內容:顯式規則、隱式規則、變量定義、文件指示和註釋。

  • 顯式規則:顯式規則說明了如何生成一個或多個目標。這需要由Makefile的書寫者顯式指出要生成的文件、文件的依賴文件及生成的命令。

  • 隱式規則:由於make有自動推導的功能,會選擇一套默認的方法進行make,所以隱式的規則可以讓開發者比較簡略地書寫Makefile,這是由make所支持的。

  • 變量定義:在Makefile中需要定義一系列的變量,一般都是字符串,它類似C語言中的宏,當Makefile被執行時,其中的變量都會被擴展到相應的引用位置上。

  • 文件指示:包括三部分,第一部分是在一個Makefile中引用另一個Makefile,就像C語言中的include一樣包含進來;第二部分是根據某些情況指定Makefile中的有效部分,就像C語言中的預編譯宏#ifdef;第三部分就是定義一個多行的命令。

  • 註釋:Makefile中只有行註釋,和UNIXshell腳本一樣,其註釋符使用“#”字符,這就像C/C++中的雙斜槓“//”一樣。如果需要在Makefile中使用“#”字符,可以用反斜槓進行轉義,如“\\#”

  • Makefile文件中的命令必須要以“Tab”鍵開始。

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

allMakefile時最終目標,main.c,foo1.c,foo2.c,foo3.c是目標所依賴的源文件,而只有一個命令“gcc main.c foo1.c foo2.c foo3.c -o all”是生成目標的方法:

  1. 文件的依賴的關係:可執行文件all依賴於main.c,foo1.c,foo2.c,foo3.c文件,如果main.c,foo1.c,foo2.c,foo3.c中的任何一個的修改日期比all文件日期新,或者是all不存在,那麼依賴關係發生。

  2. 如何生成(或更新)all文件。那個gcc命令,說明了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

自動生成依賴關係

可以使用GNUC/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 fooecho $(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


發佈了24 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章