是否有一种方法可以强制目标规则作为在变量中设置某些内容的一部分运行?
例如,假设我们有一个目标和规则:
all_mp3s:
find / -name "*.mp3" > all_mp3s
然后是一个变量:
MP3S := $(file < all_mp3s)
有没有一种方法可以确保在评估all_mp3s
变量之前创建MP3S
文件?
答案 0 :(得分:0)
没有简单直接的方法可以在分配变量之前强制评估规则。有更复杂的方法。以下是针对GNU make的。
首先让我们假设仅在文件find
不存在的情况下才想运行{slow} all_mp3s
命令,否则使用其内容。您可以使用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
还是不?
如果您将其声明为虚假,则find
命令将仅在您每次调用make all_mp3s
(或依赖于all_mp3s
的另一个目标)时运行一次。但是取决于all_mp3s
的目标也将始终被重建,这不一定是您想要的。
如果您未将其声明为phony并且文件已经存在,则find
命令将根本不会运行(除非您的其他位置需要MP3S
的值) Makefile),并且all_mp3s
的内容不会更新,这不一定是您想要的。
由于您没有在问题中提供足够的信息来决定,所以这取决于您。