在解析过程中,如何判断Make是否已经遇到过过时的include指令?

编程语言 2026-07-12

请看下面这份makefile:

bar.txt: foo.txt
    echo "X := $(file <foo.txt)" >$@

include bar.txt

$(info X is $X)

这份makefile读取 foo.txt 的内容,将它们复制到 bar.txt,并在前面插入 X :=,然后把 bar.txt 作为一个makefile片段包含进来,最后输出 X 的结果值。

使用 echo 42 >foo.txt && make 运行时,我得到如下结果:

X is 
echo "X := 42" >bar.txt
X is 42
make: 'bar.txt' is up to date.

如何去掉第一行中的 X is

我理解这是怎么回事。Makefile会被解析两次:第一次解析加载过时的 bar.txt(如果不存在则什么也不加载),打印这个过时的值,然后构建 bar.txt,重启Make,随后照常继续。

但在第一次解析时,我该如何判断是否存在过时的包含,以便避免执行 $(info ...)

请注意,我并不只是想检查 X 是否未定义,因为它可能已经被定义,但可能是过时的(如果 foo.txtbar.txt 更新则为过时)。

解决方案

在第一次解析时,如何判断我有过时的包含,以便避免执行 $(info ...)

你不能这样做,你几乎已经解释了原因。你需要在解析期间就做出判断来避免执行 $(info) 调用,而该调用本身也是在解析期间执行的。但是 make 在完全解析完makefile之前,不能也不会试图确定任何文件是否过时。

使用GNU make 时,可以通过 MAKE_RESTARTS 变量来判断当前解析是否为第一次解析,但在解析过程中没有机制来判断是否还会有另一轮解析。

目前还不清楚你在这里关注的是输出信息,还是更一般地在解析时检测是否会重启。如果是后者,那你就没辙了;如果是前者,则可以通过使用一个规则来输出这条信息来实现。让大多数其他规则依赖于这条消息规则的目标,该目标可以是伪目标(phony),这样只有在 make 确定不再需要任何重启之后,消息才会被输出。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章