我有一個文件,TMP包含:什麼導致這個奇怪的時間旅行與製造?
{
"VolumeId": "vol--22222222",
}
和一個makefile,只有包含:如預期
\cp tmp latest
grep VolumeId latest
"VolumeId": "vol--22222222",
VolumeId: vol--22222222,
:
MYFILE =latest
x:
\cp tmp $(MYFILE)
grep VolumeId $(MYFILE)
@echo $(shell grep VolumeId $(MYFILE))
如果我運行make X,我得到。如果我修改文件tmp,替換2的機智4,我得到:
\cp tmp latest
grep VolumeId latest
"VolumeId": "vol--44444444444",
VolumeId: vol--22222222,
......呵? greps返回不同的結果!第二個包含之前的文件的副本。
我跑
rm latest ; make x
我得到:
\cp tmp latest
grep VolumeId latest
"VolumeId": "vol--4444444444",
這是怎麼回事?
GNU Make 3.81。在VMWare 5. Ubuntu的12.04
更新1
這裏有一個更明顯的例子
CMD0 =$(shell date +"%s.%N")
CMD1 =date +"%s.%N"
CMD2 =date +"%s.%N"
y:
@sleep 2
@date +"%s.%N" # 2nd
@echo $(CMD0) # 1st A
@sleep 2
@date +"%s.%N" # 3rd
@sleep 2
@$(CMD1) # 4th
@sleep 2
@echo $(shell $(CMD2)) # 1st B
輸出:
1381596581.761093768
1381596579.743610973
1381596583.769058027
1381596585.774766561
1381596579.751625601
它看起來像所有的$(殼...)命令會在y配方的任何一行之前一起評估。
這有點令人吃驚(反直覺 - 這種奇怪設計的基本原理是什麼?)。如果shell命令有副作用,它會產生重要的後果。另外,我在製作手冊中找不到描述評估順序的任何文檔。
更新2
什麼是有關上述特別奇怪的是,來的辛苦了評估順序的心智模式。是否在配方的每一行之前執行任何形式的規則$(function ...)?如果是這樣,爲什麼$(CMD0)在配方之前評估,而不是$(CMD1)。 CMD0 包含 a $(f ...) - 的確如此,儘管CMD0被聲明爲延遲評估變量(即= = not:=聲明),但是確實看到了這一點。
更新3
減少它歸結爲基本組成部分:
notSafe:
backup-everything # Format executed even if backup fails
echo $(shell format-disk) | tee log.txt #
CMDX =$(shell format-disk)
alsoNotSafe:
backup-everything # Format executed even if backup fails
echo $(CMDX) | tee log.txt # Even though CMDX is a delayed evaluation variable
CMDZ =format-disk
safe:
backup-everything # Works as expected.
$(CMDZ) | tee log.txt # Evaluation of CMDZ is delayed until line is executed.
瘋狂。誰設計的?
看起來在執行命令之前shell擴展已完成。 –