Make文件中賦值等號的幾種類型(:=,?=,=)

今天有一位以前僅做過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
這裏看出,P並沒有賦值爲byebye,因爲它已經有值了。

2. := 和 = 賦值
這兩個賦值的區別在於如果表達式中包含其他的變量,那其他變量展開的時機。
:= 在賦值的時候就展開,以後不再變化;
= 在使用的時候展開,如果賦值和使用之間右部變量發生改變,則取值發生變化;

<pre name="code" class="plain">P = hello
A := $(P)
B = $(P)
P = byebye
TARGET:
        @echo $(A)
        @echo $(B)


$ make
hello
byebye


這裏看出,P取值發生改變後,A的取之並沒有重新eval,而B在使用的時候,使用的是最新的P。

爲了便於喜歡研究的同學深究,我特意上傳makefile的寶典pdf文件供大家下載:

歡迎轉載,但是請註明原出處:http://blog.csdn.net/howellzhu

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章