没有简单直接的方法可以强制在分配变量之前对规则进行评估。还有更复杂的方法。以下是 GNU make 的。
我们首先假设您只想在文件all_mp3s 不存在时运行(慢)find 命令,否则使用其内容。您可以使用 GNU make 条件:
ifeq ($(wildcard all_mp3s),all_mp3s)
MP3S := $(shell cat all_mp3s)
else
MP3S := $(shell $(MAKE) all_mp3s ; cat all_mp3s)
endif
all_mp3s:
find / -name "*.mp3" > $@
但是我如果你的 Makefile 比这个复杂,多次使用MP3S,而你真正想要的是:
- 避免多次运行超慢的
find,
- 仅在需要时运行它(并且只运行一次),
- 在文件 (
all_mp3s) 和 make 变量 (MP3S) 中获取结果,
MadScientist 有一个wonderful GNU make trick,可以在这里使用:
MP3S = $(eval MP3S := $$(shell find / -name "*.mp3"))$(MP3S)
all_mp3s:
printf '%s\n' '$(MP3S)' > all_mp3s
.PHONY: help clean
help:
printf 'MP3 finder\n'
clean:
rm -f all_mp3s
如果 MP3S recursively expanded make variable 被扩展是因为你的 Makefile 的某些部分被评估并需要它的值(例如,如果你运行 make all_mp3s 而 all_mp3s 不存在),则将运行 find 命令,它的结果存储在变量中......并且变量将被转换为simply expanded make variable,如果有的话,进一步的扩展将重用相同的,已经计算的值。
否则,如果您的 make 调用(例如 make clean 或 make help)不需要 MP3S 值,则 find 命令甚至不会运行。
all_mp3s 文件是根据 MP3S 的值生成的(而不是在其他解决方案中相反)。
但是,还有另一件重要的事情需要决定:您是否要将all_mp3s 声明为虚假目标:
.PHONY: all_mp3s
还是不行?
由于您没有在问题中提供足够的信息来决定,这取决于您。