为什么我的打印命令在这个Makefile中执行两次?



为了记录,我是根据单一Unix规范的下一个版本编写的,即第8期,并且make命令预计会包含一些新的更改。

我的make文件如下:

.PHONY: all clean inc_phony
all: main.c
${CC} -o main -D LIB_RET=1${lib_ret} main.c
clean:
rm -f inc main
inc: inc_phony
printf 'lib_ret='`date +%S` > inc
include inc

目标是,每当我输入make时,它通过将当前时间戳的第二个组件作为makefile变量插入到包含文件中,从而使main可执行,然后在编译命令行上将其指定为宏定义。我这样做是为了让自己熟悉新的工作流程。

一个我不理解的现象是,与inc目标相关的命令被执行两次(或者至少在我的终端上显示两次):

Prompt$ make
Makefile:12: inc: No such file or directory
printf 'lib_ret='`date +%S` > inc
printf 'lib_ret='`date +%S` > inc
cc -o main -D LIB_RET=127 main.c

我想问一下社区是什么导致了这一点?

我认为这可能与我在include指令中指定inc这一事实有关,并且具有虚假目标的先决条件。我不确定如何实现每次调用make时都重新制作inc的效果。

我使用的操作系统是macOS Ventura 13.1,工具链Xcode 14.2。

main.c的内容如下:

#include <stdio.h>
int main(void){ return LIB_RET; }

你看到它两次,原因如下:

您第一次看到它是因为该文件不存在,GNU make将尝试重制包含不存在的文件。所以你看到这个:

Makefile:12: inc: No such file or directory
printf 'lib_ret='`date +%S` > inc

一旦完成,make将重新执行自己,以便它可以重新开始并读取该makefile。第二次运行make时,inc文件已经存在,因此可以直接读取它。但是,这个规则:

inc: inc_phony

inc依赖于一个目标inc_phony,它被声明为假的,所以它总是被认为是过时的…这意味着依赖于它的inc也必须被认为是过时的,这意味着make将运行该规则来重新构建inc

我有点惊讶,这没有导致GNU make再次重新执行自己,基本上永远。我怀疑您使用的Mac系统没有一个文件系统,它没有足够细粒度的修改时间来识别文件何时发生了更改。或者你使用的是苹果更喜欢随他们的工具一起发布的非常老的GNU软件的一个堕落版本。

关于哪些目标可以被认为是最新的声明在草案中:

…除了被更新的目标,以便它们被处理为包含行路径名(参见include Lines)。以下)在以后的处理中不需要被认为是最新的. ...

粗体表示,我没有对引用的文本做任何修改,除了修剪了最相关的部分。

最新更新