Makefile學習之路(2) — Makefile的變數和萬用字元

Willliam_william發表於2020-12-27

Makefile學習之路(2) — Makefile的變數和萬用字元

一、變數

Makefile 也支援變數定義,變數的定義也讓的我們的 Makefile 更加簡化,可複用。
變數定義一般採用大寫字母,賦值方式像 C 語言的賦值方式一樣,如下:

A = HelloWorld

變數使用即取值時使用括號將變數括起來再加$符,如下:

echo $(A)

編寫如下Makefile
在這裡插入圖片描述

使用make命令執行,可以看到,其實他更類似與C語言中的巨集定義
在這裡插入圖片描述
另外,我們可以在echo的前面加上@符號,讓該命令不顯示出來
在這裡插入圖片描述
執行make命令可得
在這裡插入圖片描述

二、變數的分類

在makefile中有兩種變數:

1、即時變數:A := xxx
2、延時變數:B = xxx

使用:= 表示即時變數,它的值在定義的時候已經被確定了;
使用 = 表示延時變數,它只有在使用到的時候才確定,在定義時並沒有。
編寫如下Makefile

A := $(C)
B = $(C)
C = Hello

all :
	@echo A = $(A)World!
	@echo B = $(B)World!

執行make命令如下所示,可以看到,變數A在定義時就獲取C的值(此時為空),所以A為空,而變數B在使用的時候才獲取C的值,所以得到為“Hello"
在這裡插入圖片描述
然後我們將Makefile再修改一下,將變數C的定義放到最後:
在這裡插入圖片描述
執行make命令,可以看到,B依然取到了最後C的值,這是因為make在執行時會先把整個Makefile檔案讀進去解析裡面的變數。
在這裡插入圖片描述

三、變數的修改

直接使用=:=進行修改,編寫如下Makefile

A := $(C)
B = $(C)
C = 123
A = $(C)
B := $(C)

all :
	@echo A = $(A)World!
	@echo B = $(B)World!

C = Hello

執行,A被修改成了延時變數,B被修改成了即時變數
在這裡插入圖片描述
然後還有如下變數定義符號:

?=:延時變數, 如果是第1次定義才起效, 如果在前面該變數已定義則忽略這句
+=:變數附加, 它是即時變數還是延時變數取決於前面的定義

編寫如下Makefile

A := $(C)
B = $(C)
C = Hello
C ?= 123
A += World!
B += World!

all :
	@echo A = $(A)
	@echo B = $(B)

執行後可以看到,C的值並沒有被修改,提示A和B的變數型別也沒有被改變
在這裡插入圖片描述
另外,我們還可以在執行Makefile時存入變數,如下所示,註釋掉C的定義
在這裡插入圖片描述
執行不帶C變數定義和帶C變數定義的結果如下;可以看到C的定義是生效了的,而且是最早定義的。
在這裡插入圖片描述

四、 萬用字元

編寫Makefile和三個C檔案如下所示,gcc的-c參數列示只編譯不連結
在這裡插入圖片描述
然後執行make命令,執行可執行檔案
在這裡插入圖片描述
我們可以看到,當前只有三個C檔案,編寫的Makefile已經不少了,假如一個目標檔案所依賴的依賴檔案很多,那樣豈不是我們要寫很多規則,這顯然是不合乎常理的,我們可以使用萬用字元,來解決這些問題。常用的萬用字元如下所示:

%.o:表示所有的.o檔案
%.c:表示所有的.c檔案
$@ :表示目標檔案
$< :表示第1個依賴檔案
$^ :表示所有的依賴檔案

修改後的Makefile如下所示

hello : hello.o william.o like.o
	gcc -o hello $^

%.o : %.c
	gcc -c -o $@ $<

clean :
	rm -rf hello *.o

執行make命令,得到同樣的效果
在這裡插入圖片描述
另外,加入變數,Makefile可以修改為:

OBJ = hello.o william.o like.o
hello : $(OBJ)
	gcc -o hello $^

%.o : %.c
	gcc -c -o $@ $^

clean :
	-rm -rf hello $(OBJ)

執行效果如下
在這裡插入圖片描述

五、附錄

上一篇:Makefile學習之路(1) — Makefile的引入及規則
下一篇:

相關文章