Makefile 禁止从尚未生成的包含生成警告,但不禁止错误

Makefile 禁止从尚未生成的包含生成警告,但不禁止错误,makefile,gnu-make,Makefile,Gnu Make,如果我有一个makefile include foo foo: Makefile @echo 'bar::' > foo @echo "\t@echo 'bar'" >> foo bar:: @echo 'baz' -include foo foo: Makefile @echo 'bar::' > foo @echo "\t@echo 'bar'" >> foo bar:: @echo 'baz' -inc

如果我有一个makefile

include foo
foo: Makefile
    @echo 'bar::' > foo
    @echo "\t@echo 'bar'" >> foo
bar::
    @echo 'baz'
-include foo
foo: Makefile
    @echo 'bar::' > foo
    @echo "\t@echo 'bar'" >> foo
bar::
    @echo 'baz'
-include foo
bar::
    @echo 'baz'
然后,当我运行
makebar
时,我得到

Makefile:1: foo: No such file or directory
bar
baz
我想取消这个警告。如果我有一个makefile

include foo
foo: Makefile
    @echo 'bar::' > foo
    @echo "\t@echo 'bar'" >> foo
bar::
    @echo 'baz'
-include foo
foo: Makefile
    @echo 'bar::' > foo
    @echo "\t@echo 'bar'" >> foo
bar::
    @echo 'baz'
-include foo
bar::
    @echo 'baz'
然后我得到了,正如预期的那样

bar
baz
但是,如果我有一个makefile

include foo
foo: Makefile
    @echo 'bar::' > foo
    @echo "\t@echo 'bar'" >> foo
bar::
    @echo 'baz'
-include foo
foo: Makefile
    @echo 'bar::' > foo
    @echo "\t@echo 'bar'" >> foo
bar::
    @echo 'baz'
-include foo
bar::
    @echo 'baz'
我运行
makebar
,然后

baz
而我想得到的是

Makefile:1: foo: No such file or directory
make: *** No rule to make target 'foo'.  Stop.
或者至少

make: *** No rule to make target 'foo'.  Stop.

如何在不抑制错误的情况下抑制警告,以便在无法创建文件/如果目标不存在,但成功创建时没有喷涌时失败?

这是一个黑客解决方案:您可以将makefile拆分为两个,如下所示:

# Makefile

foo.mak:
    @echo running $@
    @echo 'bar::' > foo.mak
    @echo -e "\t@echo 'bar'" >> foo.mak

bar bar2 bar3: foo.mak
    @$(MAKE) --file Makefile.2 $@
然后

#Makefile.2:
include foo.mak
bar::
    @echo baz

问题是它必须为每个顶级目标调用make的新副本。我似乎记得使用了match anything规则而不是显式目标列表,但我只是尝试了一下,它似乎给我带来了问题,所以我显式地列出了目标。

我发现了一个非常棘手的解决方案,包括手动发出错误消息:

-include foo

ifeq (,$(filter-out foo,$(MAKECMDGOALS)))
ifeq (,$(wildcard foo))
$(shell $(MAKE) foo)
ifeq (,$(wildcard foo))
$(error No rule to make target 'foo')
endif
endif
endif

foo: Makefile
    @echo 'bar::' > foo
    @echo "\t@echo 'bar'" >> foo

bar::
    @echo 'baz'
也许一个稍微不那么老套的解决方案是:

ifeq (,$(filter-out foo,$(MAKECMDGOALS)))
ifeq (,$(wildcard foo))
$(shell $(MAKE) foo)
endif
include foo
else
-include foo
endif

foo: Makefile
    @echo 'bar::' > foo
    @echo "\t@echo 'bar'" >> foo

bar::
    @echo 'baz'

不久前我也遇到过类似的问题,目前还没有一个简单的解决方案。如果文件不存在,
-include
将不起任何作用,如果文件不存在,
include
将始终抛出警告。我通过使用第二个makefile解决了我的问题,但这也有它的问题。