Makefile的語法

ARM裸機1期加強版視頻課程配套WiKi第9課第6節(jié)_Makefile的語法。
文字不能完全替代視頻,所以如果你看了這些文章不太懂,建議購買視頻進一步學習。
視頻購買地址:100ask.taobao.com。
本節(jié)我們只是簡單的講解Makefile的語法,如果想比較深入學習Makefile的話可以:
a.
百度搜 “gnu make 于鳳昌”。
b. 查看官方文檔:
GNU Make Manual - GNU Project - Free Software Foundationwww.gnu.org
通配符
假如一個目標文件所依賴的依賴文件很多,我們豈不是要寫很多規(guī)則?這顯然不合乎常理。
我們可以使用通配符解決這些問題。我們對上節(jié)程序進行修改代碼如下:
test: a.o b.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
%.o:表示所用的.o文件
%.c:表示所有的.c文件
$@:表示目標
$<:表示第1個依賴文件
$^:表示所有依賴文件
在該目錄下增加一個c.c文件,代碼如下:
#include <stdio.h>
void func_c()
{
printf("This is C\n");
}
在main函數(shù)中調(diào)用修改的Makefile,修改后的代碼如下:
test: a.o b.o c.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
執(zhí)行:
make
結(jié)果:
gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -c -o c.o c.c
gcc -o test a.o b.o c.o
運行:
./test
結(jié)果:
This is B
This is C
假想目標: .PHONY
1.我們?nèi)羟宄募?,在Makefile的結(jié)尾添加如下代碼即可:
clean:
rm *.o test
1).執(zhí)行make:生成第一個可執(zhí)行文件。
2).執(zhí)行make clean: 清除所有文件,即執(zhí)行:rm *.o test。
2.使用Makefile
執(zhí)行:make [目標]
也可以不跟目標名,若無目標默認第一個目標。執(zhí)行make的時候,會在makefile里面找到第一個目標然后執(zhí)行下面的指令生成第一個目標。當執(zhí)行make clean的時候,會在Makefile里面找到clean這個目標,然后執(zhí)行里面的命令,這個寫法有些問題,原因是我們的目錄里面沒有clean這個文件,這個規(guī)則執(zhí)行的條件成立,它就會執(zhí)行下面的命令來刪除文件。
如果:該目錄下面有名為clean文件怎么辦呢?
我們在該目錄下創(chuàng)建一個名為“clean”的文件,然后重新執(zhí)行make,make clean,結(jié)果(會有下面的提示:):
make: `clean' is up to date.
它根本沒有執(zhí)行我們的刪除操作,為什么?
我們之前說,一個規(guī)則能夠執(zhí)行的條件:
1).目標文件不存在
2).依賴文件比目標新。
現(xiàn)在我們的目錄里面有名為“clean”的文件,目標文件是有的,并且沒有依賴文件,沒有辦法判斷依賴文件的時間。這種寫法會導致:有同名的”clean”文件時,沒有辦法執(zhí)行make clean操作。
解決辦法:把目標定義為假想目標,用關(guān)鍵字PHONY。
.PHONY: clean //把clean定義為假想目標。它便不會判斷名為“clean”的文件是否存在, 然后在Makfile結(jié)尾添加.PHONY: clean語句,重新執(zhí)行:make clean,就會執(zhí)行刪除操作。
變量
在makefile中有兩種變量:
· 1)簡單變量(即時變量):
A := xxx // A的值即刻確定,在定義時即確定
對于即時變量使用“:=”表示,它的值在定義的時候已被確定。
· 2)延時變量
B = xxx // B的值被使用到時才確定
對于延時變量使用“=”表示。它只有在使用到的時候才確定,在定義/等于時并沒有確定下來。
想使用變量的時候使用“$”來引用,如果不想看到命令時,可以在命令的前面加上”@”符號,則不會顯示命令本身。
當我們執(zhí)行make命令的時候,make這個指令本身,會把整個Makefile讀進去,進行全部分析,然后解析里面的變量。常用的變量的定義如下:
:= // 即時變量
= // 延時變量
?= // 延時變量, 如果是第一次定義才起效, 如果在前面該變量已定義則忽略這句
+= // 附加, 它是即時變量還是延時變量取決于前面的定義
?=: // 如果這個變量在前面已經(jīng)被定義,這句話就不會起效果。
實例:
A := $(C)
B = $(C)
C = abc
#D = 100ask
D ?= weidongshan
all:
@echo A = $(A)
@echo B = $(B)
@echo D = $(D)
C += 123
執(zhí)行:
make
結(jié)果:
A =
B = abc 123
D = weidongshan
分析:
1)
A := $(C): A為即時變量,在定義時即確定,由于剛開始C的值為空,所以A的值也為空。
2) B = (C):B為延時變量,只有使用到時它的值才確定,當執(zhí)行make時,會解析Makefile里面的所用變量,所以先解析C=abc, 然后解析C+=123,此時C=abc123,
當執(zhí)行:@echoB=(C):B為延時變量,只有使用到時它的值才確定,當執(zhí)行make時,會解析Makefile里面的所用變量,所以先解析C=abc, 然后解析C+=123,此時,C=abc123,當執(zhí)行:@echoB=(B) B的值為 abc 123。
3)
D ?= weidongshan: D變量在前面沒有定義,所以D的值為weidongshan,如果在前面添加D = 100ask,最后D的值為100ask。
我們還可以通過命令行存入變量的值
例如執(zhí)行:
make D=123456
里面的D ?= weidongshan這句話便不再起作用。
結(jié)果:
A =
B = abc 123
D = 123456