在makefile中,會經常使用shell命令,也經常見到$var 和 $$var的情況,有什麼區別呢,區別大了。不要認為在makefile的規則的命令列中使用$var就是將makefile的變數和shell共用了,這裡僅僅是讀取makefile的變數然後擴充開,將其值作為參數傳給了一個shell命令。而$$var是在訪問一個shell命令內定義的變數,而非makefile的變數。此外,如果某規則有n個shell命令列構成,而相互之間沒有用';'和'\'串連起來的話,就是相互之間沒有關聯的shell命令,相互之間也不能變數共用。看如下例子:
makefile程式碼片段1:VAR=3 target: prerequsite1 prerequsite2 echo $VAR (1) VAR=4 (2) echo $VAR (3) echo $$VAR (4)
在程式碼片段1中,(1)的結果是3,顯然makefile利用自己的變數將$VAR擴充成3之後傳遞給這個echo這個shell命令。
(2)中,是一個獨立的shell命令自己第一了一個shell變數,名字也叫VAR,且其值為4,不會影響到makefile中的VAR。
(3)中,同(1),makefile中的變數VAR的值依然是3
(4)makefile將$$VAR先執行一次擴充得到如下shell命令:
echo $VAR然後交給shell去解釋執行,可是對於這個shell命令來說VAR是一個為定義的變數,因此輸出的結果就是個空行。
makefile程式碼片段2:VAR=3 target: prerequsite1 prerequsite2 echo $VAR;\ (1') VAR=4;\ (2') echo $VAR;\ (3') echo $$VAR (4')
在程式碼片段2中,所有的shell命令都被串連起來了,那麼執行的結果就有變化了:
(1')結果同(1),$VAR被替換成了3
(2')結果同(2)
(3')輸出3,因為雖然shell中有VAR變數,可是makefile先要進行擴充,擴充的結果就是echo 3。
(4')輸出4,因為makefile擴充結果為echo $VAR,而shell中已經有了變數VAR,且其值為4.
類似的例子還有如下:
makefile代碼片斷3: SUBDIRS=tools examples src target: prerequsite1 prerequsite2 for dir in $SUBDIRS; do $(MAKE) -C $$dir;done
make首先將這個命令擴充成:
for dir in tools examples src; do make -C $dir; done
然後交給shell解釋執行,可見dir就是一個shell中的變數。
總之,在makefile的shell命令中,黨要引用shell變數的時候,要使用$$VAR格式。
此外注意一點,在makefile中,$$還被用來做SECONDEXPANSION,即二次擴充,一般是作為prerequsites.
如:
.SECONDEXPANSION (要使用這個feature就的加上這一行)
main_objs := main.o try.o test.o
lib_objs := lib.o api.o
main lib: $$($$@_objs)
$$($$@_objs)第一階段的擴充結果為$($@_objs),第2階段的擴充結果為:$@被替換為main lib,與_objs串連成main_objs lib_objs。加上外面$的擴充,就是$main_objs $lib_objs,最終結果為main.o
try.o test.o lib.o api.o