Makefile 中几乎重复的目标规则会产生什么后果?

What are the consequences of having almost duplicate target rules in a Makefile?

我继承了一个有问题的 Makefile.am,它一直导致构建问题。在这个 makefile 中,有几个实例几乎是重复的目标规则。它们几乎是重复的,因为第二个有一个或两个额外的先决条件。这是一个例子:

target1 target2: prereq1 prereq2 
        ACTION

target1 target2: prereq1 prereq2 prereq3
        ACTION

动作相同,target1和target2相同。这样做的后果是什么?两条规则都会被执行吗?

稍微扩展一下这个问题,如果在 make 过程中自动生成 prereq3,结果会怎样?如果 make 是 运行 并行,这会导致大问题吗?

假设您使用的是 gnu make,警告表明第一个规则被忽略。 运行 make 大声笑从第二个配方执行动作。可以删除第一个配方中的 ACTION(这将删除警告!)。

make

Makefile:5: warning: overriding recipe for target 'target1'
Makefile:2: warning: ignoring old recipe for target 'target1'
Makefile:5: warning: overriding recipe for target 'target2'
Makefile:2: warning: ignoring old recipe for target 'target2'
echo "Action2"
Action2

引自 gnu make 手册:https://www.gnu.org/software/make/manual/make.html

warning: overriding recipe for target xxx' warning: ignoring old recipe for targetxxx'

GNU make allows only one recipe to be specified per target (except for double-colon rules). If you give a recipe for a target which already has been defined to have one, this warning is issued and the second recipe will overwrite the first. See Multiple Rules for One Target.

The action is identical, and target1 and target2 are identical. What is the consequence of this? Will both rules be executed?

结果是基于此 Makefile.am 生成的 makefile 将逐字包含这两个规则,将不符合 makefile 的 POSIX 规范。 POSIX 禁止多个目标规则为任何给定目标提供配方。

如果您碰巧使用 GNU make 进行构建,那么它不会直接拒绝 makefile,而是会为每个目标使用最后给出的配方;每个目标的所有其他目标规则都将被视为仅先决条件规则,无论它们是否提供配方。如果您使用不同的 make(Autotools 明确支持),则结果可能会有所不同。在 Autotools 构建系统中,依赖于特定于实现的行为是非常糟糕的形式。

由于配方相同,目标相同,并且较早规则的先决条件列表是较晚规则先决条件列表的子集,因此我认为没有理由保留较早规则。只是批发删除它。在 GNU make 下,任何行为都不会改变,您不必担心其他 make 的行为因这个问题而有所不同。

然而,这确实假设 target1target2 没有 other 目标规则。如果提供配方的 target2 最后出现的规则与提供配方的 target1 最后出现的规则不同,则两个配方将 运行:一个生成target1(可能产生 target2 的副作用),另一个产生 target2(可能产生 target1 的副作用)。它们的相对顺序未指定,结果可能不一致。

您还应该阅读 the Automake manual's comments on tools and rules that generate multiple targets

To extend this question a bit, if prereq3 was auto generated during the make process, how would this play out?

与已经描述的没有什么不同,至少对于 GNU make。您描述的构造可能是出于对这个问题的误解,或者它可能针对其他 make 实现的特定于实现的行为而不是 GNU,但是如果目前,该软件使用 GNU make 正确构建,然后删除第一条规则只是将生成的 makefile 转换为符合 POSIX 的 makefile(在这方面),没有理由期望行为有任何变化。

可能存在与您具体情况相关的细微差别和替代解决方案,但无论任何此类细节如何,上述所有评论均适用。

If make is run in parallel, could this cause big issues?

您描述的规则重复与并行 make 没有特定的交互作用。但是,如果您不表达每个目标的完整依赖关系,尤其是对其他构建目标的依赖关系,您可能 运行 会遇到并行 make 的问题。但请注意,您通常不需要表达对 C 或 C++ 头文件的依赖性,甚至是构建的头文件,因为 Automake 生成的 makefile 包含用于自动检测和跟踪这些文件的代码。

但是,如果您有其他目标规则为一个或两个目标提供配方,如上所述,那么是的,这将是并行 make 的问题。帮自己一个忙,确保没有一个目标具有由多个目标规则指定的配方。

此外,虽然规则重复可能不是并行 make 的问题,但如果一个 运行 配方生成两个目标,那么 可能会导致并行 make 出现问题。有关这一点的更多评论,请参阅上面链接的 Automake 手册。