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

GNU Make: Ensure existence of prerequisite and disable implicit rule search

问题:

如何在仍然确保先决条件实际存在的同时禁用对先决条件的隐式规则搜索?

背景:

考虑以下初始 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 的输出时,我们发现即使 a 存在,make 也在搜索预定义的隐式规则拟合a为了看能不能重发。例如,如果文件 a.c 碰巧存在,那么 make 将尝试编译 a.c 以生成文件 a。为了防止这种情况,我们为 a 定义了一个带有空配方的明确规则。这给了我们更新后的 Makefile:

a: ;

b: a
    @echo MAKING B
    cp a b

现在的问题是,即使 a 不存在,make b 的配方也会运行,这会导致失败。有没有其他方法可以表明 a 应该存在,同时不搜索隐式规则来构建 a?我想在不提供 a 检查其存在的方法的情况下执行此操作。

我将尝试总结到目前为止我们讨论的状态。也许仍然有人突然出现 another/better 洞察力。

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

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

理论上,应该可以通过 defining a no recipe target rule (% : %.c) or defining a static pattern rule (a: % : %.c) 完全禁用隐式模式规则或针对特定(组)目标。尽管如此,如果存在 a.c 文件,结果行为似乎与 a: 的空规则相同。 IE。 make b 只是在没有文件 a 存在的情况下继续(我们稍后会尝试访问它)。

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

.SUFFIXES:

或者通过使用 -r(或 --no-builtin-rules)选项调用 make 来完全禁止使用隐式内置规则。然而,这些是相当严厉的,因为它们会影响 Makefile.

中所有规则的处理。

要在以下位置发表评论:

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

% : %.c
% : %.o

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

中没有 a

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

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

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


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

作为 @Stein 跟进该主题,他实际上非常有帮助地指出: "building" a 的简单(总是)失败规则就足够了。如果该名称的文件 (a) 存在,则目标 a 的规则永远不会达到 运行 它的配方。对于文件不存在的情况,我们可以有一个失败并显示错误消息的配方。