在这个例子中,我有一个需要一些时间的过程。我们说1秒。如果我写下以下Makefile
,FOO
将make all
扩展3次,make clean
则不会扩展all
。
如果我想为FOO
节省一些执行时间,我可以使用:=
代替=
分配FOO
。但是,这将导致FOO = $(shell echo -e "+1" >> foo && echo "Hello" && sleep 1)
all:
@echo $(FOO)
@echo $(FOO)
@echo $(FOO)
@cat foo
clean:
rm foo
扩展以进行目标清理,即使它不使用它也是如此。
$ make
Hello
Hello
Hello
+1
+1
+1
输出:
{{1}}
我想强制Make只在需要时才展开变量一次。
是否可以这样做?
答案 0 :(得分:2)
我能想出的“最佳”解决方案如下:
$ cat coin.mk
FOO = FOO:=$(shell echo -e "+1" >> foo && echo "Hello" && sleep 1)
defined = $(and $(filter-out undefined,$(origin $1)),$($1))
all:
echo $(eval $(FOO))$(FOO)
echo $(FOO)
echo $(FOO)
cat foo
clean:
rm foo
$ time make -f coin.mk clean
rm foo
rm: cannot remove `foo': No such file or directory
make: *** [clean] Error 1
real 0m0.003s
user 0m0.003s
sys 0m0.000s
$ time make -f coin.mk
echo Hello
Hello
echo Hello
Hello
echo Hello
Hello
cat foo
+1
real 0m1.009s
user 0m0.002s
sys 0m0.004s
$ time make -f coin.mk clean
rm foo
real 0m0.003s
user 0m0.000s
sys 0m0.003s
哪个有效但需要特殊外壳在make run中首次使用变量($(eval $(FOO))
第二次运行会导致make错误。)
我曾短暂地将eval逻辑封装在中FOO
的值,但大多数尝试都被抱怨*** Recursive variable 'FOO' references itself (eventually). Stop.
答案 1 :(得分:1)
试试这个:
FOO = $(eval FOO := $(shell echo "+1" >> foo && echo "Hello" && sleep 1))$(value FOO)
第一次make展开$(FOO)
时,它会首先展开eval
,使用FOO
重置变量:=
。然后它解析FOO
变量的值。在随后的扩展中,由于eval
,FOO
会直接扩展到该值。
我还应该指出,如果您至少拥有GNU make 4.0,那么最近可以使用添加到POSIX标准的新功能the !=
operator:
FOO != echo "+1" >> foo && echo "Hello" && sleep 1
这正是你想要的。