GNU Make:确保先决条件存在并禁用隐式规则搜索

时间:2019-01-13 19:26:58

标签: makefile gnu-make

问题:

如何在前提条件上禁用隐式规则搜索,同时又确保前提条件确实存在?

背景

请考虑以下初始Makefile

b: a
    @echo MAKING B
    cp a b

a是制作b所必需的文件。如果文件a存在,则make b成功运行。如果不存在,则会出现以下错误:

make: *** No rule to make target `a', needed by `b'.  Stop.` 

这正是我们的预期,但是在检查make --debug=a b的输出时,我们看到即使存在amake也在搜索适合{{ 1}},以查看是否可以重新制作。例如,如果文件a确实存在,那么a.c将尝试编译make来生成文件a.c。为防止这种情况,我们为a定义了一个空配方的显式规则。这为我们提供了更新的a

Makefile

现在的问题是,即使a: ; b: a @echo MAKING B cp a b 不存在,make b的配方仍在运行,这将导致失败。还有其他方法可以表明a应该存在,而不要搜索隐式规则来构建a吗?我不想提供a的食谱来检查其存在。

1 个答案:

答案 0 :(得分:3)

到目前为止,我将尝试总结我们的讨论情况。也许有人还是会冒出另一个更好的见解。

除了问题本身也提到的选项之外(有关此方法的最新迭代,请参见下面的解释器):

a:
        $(error missing file "$@")
b: a
        @echo MAKING B
        cp a b

理论上,应该defining a no recipe target rule% : %.c)或defining a {{3 }}(a: % : %.c)。但是,如果有一个a.c文件,则产生的行为似乎与a:的空规则相同。即make b仅在文件a不存在的情况下继续进行(以后我们将无法尝试访问它)。

由于至少某些隐式规则似乎已实现为static pattern rule,因此可以通过清除默认满足条件的列表来禁用对a.c之类的输入的考虑:

.SUFFIXES:

或通过调用带有-r(或--no-builtin-rules)选项的make来完全禁止使用隐式内置规则。但是,这些规则处理起来很繁琐,因为它们会影响{​​{1}}上所有规则的处理。


要在以下位置处理评论:

如前所述,禁用几个内置的C编译规则似乎会产生预期的结果,即:

Makefile

结果为% : %.c % : %.o ,而a.c中没有a

但是(像-r一样),它很麻烦,因为依赖隐式规则的所有其他目标都会受到影响。同时它并不是很远,因为它不涉及其他情况,例如make: *** No rule to make target 'a', needed by 'b'. Stop.a.Ca.cpp,...

在适用的情况下,静态规则应该能够替换模式规则(匹配时,在更通用的规则上应用更具体的规则)。但是实际上,将其限制为单个目标确实可以使其与仅特定的a,v规则相提并论。

我实际上不确定树的其余部分是什么样子以及可能发生的所有可能的构建步骤。根据目前的理解,如果名称冲突的文件成为可能和关注的问题,我仍然倾向于通过文件存在性检查来明确地定位目标。


简单失败规则的最新版本的解释:

随着suffix rules对该主题的跟进,他实际上非常有帮助地指出:建立(a:的简单(总是)失败规则就足够了。如果存在具有该名称(a)的文件,则目标a的规则将永远无法运行其配方。对于文件不存在的情况,我们可以使用一个失败的配方并显示一条错误消息。