今天有一位以前僅做過Android APP開發的同學突然間問我,說Makefile中經常可以看見:冒號等號(:=)、問號等號(?=)和直接等號(=)。這究竟有什麼區別呢?
歡迎轉載,但是請註明原出處:http://blog.csdn.net/howellzhu
突然想到團隊中其實有些同學以前沒有做過Android整個源碼樹或者native代碼的修改和開發,因此對Makefile有些陌生。這裏簡單的介紹一下三者的區別,其實非常簡單:
1) ?=: 條件賦值(conditional variable assignment),如果變量已經賦值,則不要重新賦值;
2) :=: 立即賦值(immediately assignment),變量取值立即展開;
3) =: 遞歸展開賦值(recursively expanded assignment),該變量在使用的時候纔對表達式進行展開;
對於後面的2)、3),稍微難以理解一點,但是隻要我給出下面的表達式大家立即就會理解了:
VAR1 = $VAR2 + postfix
對頭,區別就是如果變量的表達式中包含另外的變量如何處理。立即賦值立刻取值展開,以後VAR1和VAR2就沒有關係了;遞歸展開賦值在後面使用VAR1的時候才真正根據VAR2的取值來計算,
如果期間VAR2的取值發生變換,VAR1的取值也是變化的。
下面看幾個例子加深理解:
歡迎轉載,但是請註明原出處:http://blog.csdn.net/howellzhu
1. ?=
這個非常簡單,就是說符號已經定義,就不要進行賦值。
P = hello
P ?= byebye
TARGET:
@echo $(P)
$ make
hello
hello
這裏看出,P並沒有賦值爲byebye,因爲它已經有值了。
2. := 和 = 賦值
這兩個賦值的區別在於如果表達式中包含其他的變量,那其他變量展開的時機。
:= 在賦值的時候就展開,以後不再變化;
= 在使用的時候展開,如果賦值和使用之間右部變量發生改變,則取值發生變化;
<pre name="code" class="plain">P = hello
A := $(P)
B = $(P)
P = byebye
TARGET:
@echo $(A)
@echo $(B)
$ make
hello
byebye
hello
byebye
這裏看出,P取值發生改變後,A的取之並沒有重新eval,而B在使用的時候,使用的是最新的P。
爲了便於喜歡研究的同學深究,我特意上傳makefile的寶典pdf文件供大家下載:
歡迎轉載,但是請註明原出處:http://blog.csdn.net/howellzhu