假的目标在makefile中

我试图在这个链接中执行示例。

all : prog1 prog2 prog3 .PHONY : all prog1 : prog1.o utils.o cc -o prog1 prog1.o utils.o prog2 : prog2.o cc -o prog2 prog2.o prog3 : prog3.o sort.o utils.o cc -o prog3 prog3.o sort.o utils.o 

有或没有PHONY(如果我注释.PHONY线),输出是相同的。 这里PHONY的真正用途是什么?

文章提到这一点

When one directory contains multiple programs, it is most convenient to describe all of the programs in one makefile

Since the target remade by default will be the first one in the makefile, it is common to make this a phony target named 'all' and give it, as prerequisites, all the individual programs

我不明白这里PHONY的真正用途是什么。 在这个例子中,如果没有PHONY,程序的行为会有所不同,有人可以指出一个场景吗?

没有.PHONY“全部”只是一个正常的目标,这取决于prog1,prog2,prog3。 这意味着,如果一个名为“all”的文件恰好存在于比prog1,prog2和prog3更新的目录中,那么它们将不会被构建(尝试它!) – 但这显然不是您想到的。

.PHONY告诉GNU make“all”目标是假的 – 你不是真的打算创建一个名为“all”的文件,它应该建立依赖关系,不管是否存在一个名为“all”的文件。

稍后添加:

尽管总体思路是正确的,但我和上面所有人和prog1的例子并不正确。 这是一个非常简单的例子

 all: prog prog: prog.c clean: $(RM) prog prog.o giladb@xxx:~/tmp$ ls Makefile prog.c giladb@xxx:~/tmp$ make cc prog.c -o prog giladb@xxx:~/tmp$ make clean rm -f prog prog.o giladb@nps06:~/tmp$ make cc prog.c -o prog giladb@xxx:~/tmp$ touch clean giladb@xxx:~/tmp$ make clean make: `clean' is up to date. 

至少对于GNU Make和这个例子来说,无论目标“全部”是否是假目标,输出的行为都是一样的。 即使有一个名为“全部”的文件。

但是正如后面链接手册中所描述的那样,GNU Make的内部行为是不同的。 如果“all”不是假目标,GNU Make将检查名为“all”的文件是否存在并且比其先决条件早。 尝试“make -d”,你会看到不同之处。

另外重要的一点是假目标的配方总是被执行。 如果你拿这个例子:

 all: goal echo "Done" .PHONY : clean goal: echo "Hello World!" > $(@) clean: rm -f goal all 

…并执行此操作:

 $ make clean rm -f goal all $ make echo "Hello World!" > goal echo "Done" Done $ make echo "Done" Done $ touch all $ make make: 'all' is up to date. 

…创建文件“全部”后,配方将不会执行。

以“全部”为假目标:

 all: goal echo "Done" .PHONY : all clean goal: echo "Hello World!" > $(@) clean: rm -f goal all 

…“all”的配方将被执行,而不管文件“all”的存在。

 $ make clean rm -f goal all $ make echo "Hello World!" > goal echo "Done" Done $ make echo "Done" Done $ make echo "Done" Done $ touch all $ make echo "Done" Done $ make echo "Done" Done