强制变量扩展一次,仅在使用时

时间:2015-02-16 11:36:06

标签: makefile

在这个例子中,我有一个需要一些时间的过程。我们说1秒。如果我写下以下MakefileFOOmake 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只在需要时才展开变量一次。

是否可以这样做?

2 个答案:

答案 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变量的值。在随后的扩展中,由于evalFOO会直接扩展到该值。

我还应该指出,如果您至少拥有GNU make 4.0,那么最近可以使用添加到POSIX标准的新功能the != operator

FOO != echo "+1" >> foo && echo "Hello" && sleep 1

这正是你想要的。