Makefile:如何检测Makefile本身内的更改?

Makefile:如何检测Makefile本身内的更改?,makefile,Makefile,我知道使用递归生成文件的想法。是否会仅在对后续makefile本身进行任何更改时更新后续makefile(如以下所示) e、 g: 如果subdir中的makefile发生了更改,导致以下内容不适用(例如,仅更改了gcc标志),那么是否会更新对象文件 如果源文件或任何 名为dependencies的头文件比对象更新 文件,或者如果对象文件不存在 正如所写的,使该规则均匀运行的唯一原因是子系统和子系统不匹配 如果在该目录中创建了子系统文件或目录,则该规则将停止运行 如果添加了.PHONY:subs

我知道使用递归生成文件的想法。是否会仅在对后续makefile本身进行任何更改时更新后续makefile(如以下所示)

e、 g:

如果subdir中的makefile发生了更改,导致以下内容不适用(例如,仅更改了gcc标志),那么是否会更新对象文件

如果源文件或任何 名为dependencies的头文件比对象更新 文件,或者如果对象文件不存在


正如所写的,使该规则均匀运行的唯一原因是
子系统
子系统
不匹配

如果在该目录中创建了
子系统
文件或目录,则该规则将停止运行

如果添加了
.PHONY:subsystem
,则问题将得到解决,并且当在命令行上列出该规则时(即
生成子系统
),该规则将始终运行。(如注释
所示。PHONY
是GNU Make的扩展。链接部分后面的部分讨论了一种可移植的替代方案。尽管值得注意的是,它们在
方面并不完全相同。PHONY
有一些额外的好处和限制。)

在这两种情况下,
子系统
目标都没有注意任何东西的修改日期(因为它没有列出任何先决条件)

要使目标依赖于对makefile的更改,您需要将makefile与其他任何内容一样列为先决条件(即
子系统:subdir/makefile
)。将其列为
.PHONY
可能更正确,也更符合您的需求

不,make中没有跟踪非先决条件的内容。因此,标记更改/等不会触发重建。但是,有一些方法可以使make工作(它们涉及将使用的标志存储在文件中,这些文件本身是使用这些标志的目标的先决条件,等等)。关于这样做,有很多问题和答案(但我没有马上准备好)


但是,其他工具会自动处理标记更改。我相信我们的工具可以做到这一点。我相信也一样。也可能有其他文件。

您可以将makefile作为依赖项包含,与任何其他文件相同:

mytarget.o: mytarget.c Makefile

无论是否有任何更改,都会执行递归生成文件。这正是保罗·米勒(Paul Miller)在近20年前的论文中指出的反对意见之一


话虽如此,makefile与任何其他依赖项一样,可以添加到生产规则中,以便在makefile被更改时触发该规则。

.PHONY
是有用的,但您可能需要指出,它是GNU make中的一个扩展,但在make实现中通常不存在。等等,如果您提到makefile作为先决条件,它不会检测到目标makefile是否有任何更改吗?更具体地说,如果您更改了目标makefile的配方中的标志,那么该makefile是完全运行还是只是进入并退出它而不实际执行任何操作?(你暗示了后者)。这是考虑到整个构建已经完成,并且只更改了一个配方中的标志(除了目标makefile本身之外,makefiles中的任何目标都不会更改。“不,make本身中没有跟踪非先决条件的内容。”让我感到困惑。@imagineer修改(出于make的目的)makefile列为先决条件,它将触发任何将其列为先决条件的目标,是的。就像普通先决条件一样。make不够聪明,无法知道您修改了哪个目标(如果修改的makefile中有多个目标)。但是,如果没有任何目标先决条件发生更改,则更改标志不会导致重新生成使用该标志的目标。在这种情况下,是否会检测到依赖项生成文件中的任何文本更改?@imagineerThis Yes,这将在此处触发对生成文件的任何更改的重新生成。是否与此目标相关。@EtanReisner是co更正-不可能(甚至理论上)判断给定目标是否有更改,因为我们不知道上次编译时makefile说了什么。可以知道,但您需要显式记录所有相关信息。在某种程度上,这就是跟踪此更改的工具(我在回答中提到)如果您只是简单地确保项目中的所有makefile都被指定为prereq,直到初始的“parent”makefile,那么您不知道所有makefile的所有文本更改吗?唯一的问题是,如果没有文本更改,但子makefile中的目标发生了更改,那么该makefile将不会运行。阅读效果很好。使用单个makefile似乎是一个经过深思熟虑的解决方案。
mytarget.o: mytarget.c Makefile