如何在变量赋值中获得“最多一次”语义?

时间:2018-06-09 07:13:18

标签: makefile gnu-make

Shell命令有时需要很长时间才能运行,因此您可能不希望VAR = $(shell slow-cmd)(使用=,每次引用变量时都会运行slow-cmd)。使用VAR := $(shell slow-cmd)可能很有用,但如果您正在构建一个不需要扩展变量的目标,那么您将再次调用slow-cmd。在下面的makefile(使用gnu-make)中,您可以获得所需的行为:定义V2值的shell命令永远不会被多次调用,对于目标foo,它根本不会被调用。但这是一个令人发指的污垢。是否有更合理的方法来确保变量仅在需要时定义,但从未评估过多次?

V1 = $(shell echo evaluating V1 > /dev/tty; echo V1 VALUE)

all: foo bar V2
        @echo $(V1) $@
        @echo $(V2) $@

foo:
        @echo $(V1) $@

bar: V2
        @echo $(V1) $@
        @echo $(V2) $@

V2:
        $(eval V2 := $(shell echo evaluating V2 > /dev/tty; echo V2 VALUE))

.PHONY: all foo bar

2 个答案:

答案 0 :(得分:5)

如果没有技巧,就没有办法做到这一点,但是有一种比你正在使用更清洁的方式(也许)。您可以使用:

V1 = $(eval V1 := $$(shell some-comand))$(V1)

有关详细信息的详细信息和解释,请参阅this page

答案 1 :(得分:0)

特定于目标的延迟变量是一个选项:

host> cat Makefile
foo: VFOO = $(shell echo "VFOO" >> log.txt; echo "VFOO")

foo:
    @echo '$(VFOO)' > $@

bar: VBAR = $(shell echo "VBAR" >> log.txt; echo "VBAR")

bar:
    @echo '$(VBAR)' > $@

host> make foo
host> cat log.txt
VFOO
host> make foo
make: 'foo' is up to date.
host> cat log.txt
VFOO
host> make bar
host> cat log.txt
VFOO
VBAR
host> make bar
make: 'bar' is up to date.
host> cat log.txt
VFOO
VBAR