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

jus*_*npc 5 makefile gnu-make

题:

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

背景:

考虑以下初始Makefile

b: a
    @echo MAKING B
    cp a b
Run Code Online (Sandbox Code Playgroud)

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

make: *** No rule to make target `a', needed by `b'.  Stop.` 
Run Code Online (Sandbox Code Playgroud)

这正是我们所期望的,但是,在检查的输出时make --debug=a b,我们发现即使a存在,也make正在搜索适合的预定义隐式规则a,以查看是否可以重新生成它。例如,如果文件a.c恰好存在,make则将尝试编译a.c以生成文件a。为避免这种情况,我们为a带有空配方的定义了明确的规则。这给了我们更新的Makefile

a: ;

b: a
    @echo MAKING B
    cp a b
Run Code Online (Sandbox Code Playgroud)

现在的问题是make b即使a不存在运行方法,这也会导致失败。a在没有寻找要建立的隐式规则的同时,还有其他方法表明应该存在a吗?我想这样做而不给出a检查其存在的方法。

Ond*_* K. 6

我将尝试总结迄今为止我们的讨论情况。也许有人仍然会突然提出另一种/更好的见解。

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

a:
        $(error missing file "$@")
b: a
        @echo MAKING B
        cp a b
Run Code Online (Sandbox Code Playgroud)

理论上,应该可以通过定义无配方目标规则( % : %.c)或定义静态模式规则( ) 来完全禁用隐式模式规则或针对特定(组a: % : %.c)目标。尽管如此,如果存在文件a.c,结果行为似乎与a:. make b即,在文件不存在的情况下继续操作(a我们稍后会尝试访问它失败)。

由于至少一些隐式规则似乎是作为后缀规则实现的,因此可以a.c通过清除默认后缀列表来禁用对输入的考虑:

.SUFFIXES:
Run Code Online (Sandbox Code Playgroud)

-r或者通过使用(或) 选项调用 make 来完全禁止使用隐式内置规则--no-builtin-rules。然而,这些措施相当严厉,因为它们影响整个 .NET 中所有规则的处理Makefile


要在以下位置发表评论:

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

% : %.c
% : %.o
Run Code Online (Sandbox Code Playgroud)

会导致a.c存在且不a存在make: *** No rule to make target 'a', needed by 'b'. Stop.

然而(如 -r)它相当具有侵入性,因为依赖隐式规则的所有其他目标都会受到影响。但与此同时,它的影响并不那么深远,因为它不涵盖其他情况,如a.Ca.cppa,v、...

静态规则应该能够在适用的情况下替换模式规则(匹配时将更具体的规则应用于更通用的规则)。但事实上,将其限制为单一目标基本上使其与特定a:规则相当。

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


最新版简单失败规则说明:

正如@Stein继续讨论这个话题一样,他实际上非常有帮助地指出:简单(总是)失败的“构建”规则a就足够了。如果该名称的文件 ( a) 存在,则目标规则a永远不会运行其配方。对于文件不存在的情况,我们可以只使用一个失败并显示错误消息的配方。