通过前面的一篇博客知道规则是组成makefile的基本单位,而规则中又包含了三部分,先决条件其实也是目标,那么就可以分为目标和命令两大类,这里就有一个问题了,目标究竟是什么?
前面我们也说过目标的含义,应该是要生成的可执行文件,或者已经存在为文件。因为make涉及出来就是为了自动维护编译C的源码,所以make默认目标都应该对应着文件,make通过比较文件的依赖去编译最终生成可执行文件。
到这里我们就知道目标究竟是什么了,但是有时候这样不利于我们队源码进行编译。如下:
clean :
rm *.o hello.out
如果clean对应的文件不存在,我们知道这个make clean总会执行,那要是clean对应的文件存在,make clean就不会起作用了,这样就不符合我们的初衷了,所以这里我们不想clean是一个目标,而是一个伪目标或者称之为标签,标签就是说始终认为它对应为文件不存在,这样的话标签的命令不管有没有先决条件总是会发挥作用了,无非就是先决条件中的目标会不会被执行的问题。
我们首先对伪目标特性做一个总结:
伪目标不对应任何实际文件
不管伪目标的依赖是否更新,命令总是会被执行
知道了伪目标的作用,我们还需要知道非常重要的一点,就是伪目标需要先定义后使用,如下定义一个伪目标
.PHONY : all clean
通过定义我们可得知伪目标的本质,就是目标为.PHONY的先决条件。
现在知道了伪目标的使用方法和特性,我们可以做一点文章,利用伪目标来模仿一下过程调用,如下:
.PHONY : all clean rebuild
#all生成可执行文件,clean删除可执行文件和中间生成的文件
rebuild : clean all
分析一下,首先是定义了三个伪目标,当我们使用make rebuild的时候,发现clean和all都是伪目标,那么clean的动作总会被执行,all的动作也总会执行,那就相当于删除又编译了一下。这其中利用的就是伪目标的特性。
在某些非标准的GNU make中,是没有.PHONY关键字的,那我们还能不能构造一个伪目标出来,让它的命令总是执行呢,当然可以了,为了做到这点,我们需要知道一个特性,如果一个目标没有先决条件或者命令,并且它对应的文件不存在,那这个目标始终是最新的。利用这个特性我们可以避开.PHONY来构造伪目标
TEST :
clean : Test
rm *.o hello.out
TEST总是最新的,clean不管对应的目标是否存在,根据前面博客我们总结的什么时候目标会执行,我们可以知道clean总是会执行,这样就达到了避开.PHONY关键字构造伪目标的效果了。