.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中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,导致命令不被执行。