hello.out all : func.o main.o gcc -o hello.out func.o main.o func.o : func.c gcc -o func.o -c func.c main.o : main.c gcc -o main.o -c main.c clean : rm *.o hello.out
我们来看看在进行 make 之前和 make clean 之后的效果
我们看到 clean 这个目标已经被成功执行,下来我们在文件夹中建立一个 clean 文件,再来看看
我们看到再次执行 make clean 命令时,它说 clean是最新的,并没有去执行这个命令。其原因就是在文件夹中存在一个同名文件,它去执行时发现这个文件是存在的,并且在时间上更新,因此便不会去执行这个命令了。那么有什么方法可以去解决这个问题呢?在 makefile 中,有个伪目标的概念:a> 通过 .PHONY 关键字声明一个伪目标;b> 伪目标不对应任何实际的文件;c> 不管伪目标的依赖是否更新,命令总是执行。伪目标的语法是先声明,后执行。其本质是 make 中特殊目标 .PHONY 的依赖。
下来我们还是以代码为例来看看伪目标是怎样来使用的
hello.out all : func.o main.o gcc -o hello.out func.o main.o func.o : func.c gcc -o func.o -c func.c main.o : main.c gcc -o main.o -c main.c .PHONY : clean clean : rm *.o hello.out
我们来看看编译效果
我们看到不管有没有 clean 文件,makefile 总是能执行 clean 这个目标。下来我们来看看伪目标的妙用:规则调用(类似于 C 语言中的函数调用)。它的原理是当一个目标的依赖包含伪目标时,伪目标所定义的命令总是会被执行。
下来我们还是以代码为例来进行说明
hello.out : func.o main.o gcc -o hello.out func.o main.o func.o : func.c gcc -o func.o -c func.c main.o : main.c gcc -o main.o -c main.c .PHONY : rebuild clean all rebuild : clean all all : hello.out clean : rm *.o hello.out
我们来分析下,伪目标 rebuild 依赖于 clean 和 all。而 clean 是删除生成的 .o 和 hello.out 文件,all 是依赖于 hello.out。也就是说 rebuild 的作用是相当于重编译,清理完之后再次进行编译工作。下来我们来看看效果
那么 .PHONY 是标准的 makefile 中的关键字,GNU 中是支持标准的 makefile 的,而有些编译器则是不支持标准的 makefile 的。在 .PHONY 关键字失效的情况下,我们又是怎么进行伪目标的定义的呢?原理就是如果一个规则没有命令或者依赖,并且它的目标不是一个存在的文件名;在执行此规则时,目标总会被认为是最新的。
下来我们还是以代码为例来进行分析说明
hello.out all : func.o main.o gcc -o hello.out func.o main.o func.o : func.c gcc -o func.o -c func.c main.o : main.c gcc -o main.o -c main.c clean : FORCE rm *.o hello.out FORCE:
我们来看看 make clean 是否还会有效?
我们看到虽然没有伪目标 .PHONY 的定义,但是由于我们使用了这个小技巧,我们的 clean 目标还是被执行了。通过对伪目标的学习,总结如下:1、默认情况下,make 认为目标对应着一个文件;2、.PHONY 用于声明一个伪目标,伪目标不对应实际的文件;3、伪目标的本质是 make 中特殊目标 .PHONY 的依赖;4、使用伪目标可以模拟“函数调用”。
欢迎大家一起来学习 makefile 语言,可以加我QQ:243343083。
原文地址:http://blog.51cto.com/12810168/2127899