GNU make 总是认为一个非文件目标被重新制作(可能的错误?)

drw*_*ode 5 makefile gnu-make

Make是否应该始终重新制作具有先决条件但不指向文件且没有配方的目标?或者,如果需要重新制作一个或多个先决条件,Make应该只重新制作此类目标吗?

例如,在下面显示的 Makefile 中,我添加了一个名为的目标objects,该目标具有先决条件,但不指向文件。调用主要目标program取决于objects(以及可能的其他先决条件)。

file1 file2 file3: ;       touch $@

objects: file1 file2

program: objects  file3 ;  @echo 'Making $@'
Run Code Online (Sandbox Code Playgroud)

我的期望是,何时make program运行并且不需要重新制作文件先决条件(即文件 1、文件 2 和文件 3 都存在),program不应重新制作。

然而,实际的 GNU Make行为是program始终运行的配方(无论先决条件文件如何)。这是因为objects总是被认为是重新制作的,这会强制重新制作任何依赖项(即program)。

您可以通过运行来验证这一点:make --trace -d --no-builtin-rules program并且您会看到Make总是输出“ Must remake target 'objects'。 ” Soobjects总是“remade”(即使它没有配方)并且它总是被认为是新更新的。

这很可能是因为objects不指向真实文件。但我期待因为它没有配方,只要不需要重新制作它的先决条件,它就不会被重新制作。

这是预期的行为还是错误?

GNU进行手动状态:

如果规则没有先决条件或配方,并且规则的目标是一个不存在的文件,则 make 会认为该目标在其规则运行时已更新。这意味着依赖于该目标的所有目标将始终运行其配方。

但该描述不适用于上述情况,因为objects目标确实有先决条件。但也许行为是相同的,应该更新Make手册以澄清这一点。

一些额外的注意事项:

  • 我使用了上面的recipe-after-semicolon 格式,让读者更容易复制和粘贴代码。否则,从网页复制时,制表符将转换为通常的制表符缩进配方格式的空格。

  • 当然,我知道我可以创建一个$(OBJECTS)指向文件列表的变量,并用它代替objects 上面的目标。这不是重点。

  • 这个问题似乎也涉及相同的行为,但没有讨论它是预期的行为还是错误。

  • 我正在使用 GNU Make 4.2.1

Oli*_*rth 8

我相信您引用的段落只是在重述已经在其他地方指定的特定行为案例,以便为FORCE工作原理设定场景。

确实,在上一节中做了一个更简单但更通用的陈述:

如果您编写的规则的配方不会创建目标文件,则每次重新制作目标时都会执行该配方。

再次在这里

如果目标不存在或早于任何先决条件,则目标已过期。

因此,您所观察到的行为完全在意料之中。