Makefile中.PHONY的作用

.PHONY的引入

一般情况下,我们编写的Makefile中会有这样一个目标,执行make该目标会清除编译过程中产生的中间文件和生成的最终目标文件。

为了测试,这里编写一个简单的Makefile文件。该Makefile中并不提供编译源码的规则,只提供了一个clean目标,希望执行make clean时删除当前目录及子目录下所有的.o文件

clean:
    rm $(shell find -name "*.o")

现在我们的路径中有bulit-in.o main.o Makefile这三个文件,执行make clean

~/PHONY$ ls
bulit-in.o  main.o  Makefile
~/PHONY$ make
rm ./main.o ./bulit-in.o

目前一切顺利,执行make clean清除目录下所有的.o文件,达到了我们前面的期望的效果

别急,再来看这种情况,路径中有built-in.o main.o clean Makefile这四个文件,执行make clean

~/PHONY$ touch main.o bulit-in.o clean
make clean
make: 'clean' is up to date.

到这里出现了问题,执行make clean并没有删除当前目录下所有的.o文件。

出现这种现象原因是因为由于当前目录中有和clean目标同名的文件存在,Makefile中clean目标也没有相关的依赖,make机制判断clean目标已经是最新的,后面的命令永远不会被执行。

这种情况就和我们的想法冲突了,我们想要的是无论clean目标是否存在,都应该执行clean目标下的命令。基于这种需求,就引入了Makefile中的.PHONY(伪造)目标。

.PHONY的作用

PHONY:即假的,伪造的意思,编写Makefile规则中经常使用到.PHONY:“目标文件”来修饰这个“目标文件”是一个伪造的目标文件。

伪造的目标文件意味着执行规则命令并不会生成这个目标文件,所以它的命令在每次make该目标时都会执行,并不会去考虑该目标文件是否存在。

修改上面Makefile,使用.PHONY修饰clean目标是一个伪目标

.PHONY:clean
clean:
    rm $(shell find -name "*.o")

这里clean目标变成了一个伪造目标,执行"make clean"会无视"clean"文件存在与否。

~/PHONY$ ls
bulit-in.o  clean  main.o  Makefile
~/PHONY$ make
rm ./main.o ./bulit-in.o
~/PHONY$ ls
clean  Makefile

小结

Makefile中不会被在执行规则命令后生成的目标称为伪目标,可以使用.PHONY修饰一个伪目标。使用.PHONY修饰一个目标为伪目标,可以防止在Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,导致命令不被执行。

posted on 2021-01-03 22:38  quinoa  阅读(1787)  评论(0编辑  收藏  举报