我希望(GNU)make
在变量发生变化时重建。我怎样才能做到这一点?
例如,
$ make project
[...]
$ make project
make: `project' is up to date.
......应该是这样,但我更喜欢
$ make project IMPORTANTVARIABLE=foobar
make: `project' is up to date.
重建部分或全部project
。
Make 并非旨在引用可变内容,但 Reinier 的方法向我们展示了解决方法。不幸的是,使用变量值作为文件名既不安全又容易出错。希望 Unix 工具可以帮助我们正确编码值。所以
IMPORTANTVARIABLE = a trouble
# GUARD is a function which calculates md5 sum for its
# argument variable name. Note, that both cut and md5sum are
# members of coreutils package so they should be available on
# nearly all systems.
GUARD = $(1)_GUARD_$(shell echo $($(1)) | md5sum | cut -d ' ' -f 1)
foo: bar $(call GUARD,IMPORTANTVARIABLE)
@echo "Rebuilding foo with $(IMPORTANTVARIABLE)"
@touch $@
$(call GUARD,IMPORTANTVARIABLE):
rm -rf IMPORTANTVARIABLE*
touch $@
在这里,您实际上将您的目标依赖于一个名为的特殊文件$(NAME)_GUARD_$(VALUEMD5)
,该文件可以安全地引用并且与变量的值具有(几乎)一对一的对应关系。注意call
和shell
是 GNU Make 扩展。
您可以使用空文件来记录变量的最后一个值,方法如下:
someTarget: IMPORTANTVARIABLE.$(IMPORTANTVARIABLE)
@echo Remaking $@ because IMPORTANTVARIABLE has changed
touch $@
IMPORTANTVARIABLE.$(IMPORTANTVARIABLE):
@rm -f IMPORTANTVARIABLE.*
touch $@
运行后make
,目录中将有一个空文件,其名称以开头IMPORTANTVARIABLE.
并附加了变量的值。这基本上包含有关变量的最后一个值是什么的信息IMPORTANTVARIABLE
。
您可以使用这种方法添加更多变量,并使用模式规则使其更加复杂——但这个示例为您提供了它的要点。
您可能想要使用ifdef
或ifeq
取决于最终目标是什么。有关示例,请参见此处的手册。
我可能会迟到答案,但这是使用Make 条件语法进行这种依赖的另一种方法(适用于 GNU Make 4.1、GNU bash、Bash on Ubuntu on Windows 版本 4.3.48(1)-release (x86_64-pc -linux-gnu)):
1 ifneq ($(shell cat config.sig 2>/dev/null),prefix $(CONFIG))
2 .PHONY: config.sig
3 config.sig:
4 @(echo 'prefix $(CONFIG)' >config.sig &)
5 endif
在上面的示例中,我们$(CONFIG)
通过在签名文件的记录值与变量的记录值不同的条件下生成的同名目标来跟踪变量,将其值写入签名文件$(CONFIG)
。请注意第 1 行和第 4 行的前缀:当签名文件尚不存在时,需要区分大小写。
当然,消费者目标指定config.sig
为先决条件。