目錄Makefile手冊中"+=",":=","?="操作符的區別1."?="操作符2."+="操作符3.":="操作符 Makefile手冊中"+=",":=","?="操作符的區別 1."?="操作符 在GNUmake中,有一個變數在之前沒有被賦值的情況下才會對這個變數進行賦值的操作,被稱為條件 ...
目錄
Makefile手冊中"+=",":=","?="操作符的區別
1."?="操作符
在GNUmake中,有一個變數在之前沒有被賦值的情況下才會對這個變數進行賦值的操作,被稱為條件賦值操作符"?="。因此
FOO ?= bar
其等價於
ifeq ($(origin FOO), undefined)
FOO = bar
endif
含義:如果變數"FOO"在之前沒有被定義,就對此變數賦值"bar",否則不改變它的值。
2."+="操作符
通常,一個通用變數在定義之後的其他一個地方,可以對其值進行追加。這是非常有用的。我們可以在定義時(也可以不定義而直接追加)給它賦一個基本值,後續根據需要可隨時對它的值進行追加(增加它的值)。在 Makefile 中使用"+="(追加方式)來實現對一個變數值的追加操作。因此
objects = main.o foo.o bar.o utils.o
objects += another.o
其等價於
objects = main.o foo.o bar.o utils.o
objects = main.o foo.o bar.o utils.o another.o
"+="操作符在不同的情況下,含義是不一樣的
1.如果被追加值的變數之前沒有定義,那麼,“+=”會自動變成“=”,此變數就被定義為一個遞歸展開式的變數。如果之前存在這個變數定義,那麼“+=”就繼承之前定義時的變數風格。
2.直接展開式變數的追加過程:變數使用“:=”定義之後“+=”操作將會首先替換展開之前此變數的值,然後在末尾添加需要追加的值,並使用“:=”重新給此變數賦值。實際的過程像
下邊那樣:
variable := value
variable += more
就是:
variable := value
variable := $(variable) more
3.遞歸展開式變數的追加過程:一個變數使用“=”定義之後“+=”操作時不對之前此變數值中的任何引用進行替換展開,而是按照文本的擴展方式(之前等號右邊的文本未發生變化)替換,爾後在末尾添加需要追加的值,並使用“=”給此變數重新賦值。實際的過程和上邊的相類似:
variable = value
variable += more
就是:
temp = value
variable = $(temp) more
當然了,上邊的過程並不會存在中間變數:“temp”,使用它的目的時方便描述。這種情況時如果“value”中存在某種引用,情況就有些不同了。看我們通常一個會用到的例子:
3.":="操作符
為了避免“遞歸展開式”變數即使用"="定義的變數存在的問題和不方便。GNU make 支持另外一種風格的變數,稱為“直接展開”式。這種風格的變數使用":="定義。在使用":="定義變數時,變數值中對其他變數或者函數的引用在定義變數時被展開(對變數進行替換)所以變數被定義後就是一個實際需要的文本串,其中不再包含任何變數的引用。因此
x := foo
y := $(x) bar
x := later
其等價於
y := foo bar
x := later
和遞歸展開式變數不同:此風格變數在定義時就完成了對所引用變數和函數的展開,因此不能實現對其後定義變數的引用。如:
y := $(x) bar
x := later
其等價於
y := bar
x := later
由於變數"x"的定義出現在"y"定義之後。因此在"y"的定義中,"x"的值為空。"y"的值為"bar"而不是"later bar"。這一點也是直接展開式和遞歸展開式變數的不同點。