1. makefile 中的目标究竟是什么?
(1)默认情况下,make 认为目标对应着一个文件 ======> 目标即文件名
(2)make首先会检测目标对应的文件是否存在。若不存在则执行依赖和命令,若存在则会比较目标文件和依赖文件的新旧关系,决定是否执行命令。
-
在 make 中,通过比较目标文件和依赖文件的时间戳,来判断两者的新旧关系。make 程序使用的时间戳的类是 mtime(modify time),即文件发生修改的时间。
-
在 linux 中,有三个时间的概念,修改时间 mtime(modify time)、访问时间 atime(access time)、状态改间 ctime(change time)。
(3)make 以文件处理作为第一优先级。
2. 伪目标的引入
下面的代码有什么意义?
make clean意义:
执行 make clean 会将第2课中编译生成的中间 .o 文件和 hello.out 目标文件删除。但如果该目录下存在名为 clean 的文件就会导致删除命令执行失败。
有时我们并不希望目标对应的都是文件,而只是把目标当作一个标签来使用,这就引入了makefile中的伪目标。
(1)makefile中的伪目标
-
-
通过 .PHONY 关键字声明一个伪目标
-
伪目标不对应任何实际的文件(目录下有同名的文件也不会影响执行)
-
不管伪目标的依赖是否更新,命令总是执行
-
(2)makefile伪目标的语法:先声明,后使用
-
- 本质:伪目标是 make 中特殊目标 .PHONY 的依赖。
【编程实验】
# makefile伪目标的引入
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
运行结果:
(3)makefile 伪目标的妙用:规则调用(函数调用)
原理:当一个目标的依赖包含伪目标时,伪目标所定义的命令总是会被执行。当执行 make rebuild 时首先会删除之前编译生成的垃圾文件,然后重新编译整个工程。
# makefile中利用伪目标实现规则调用 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
运行结果:
(4)技巧:绕开 .PHONY 关键字定义伪目标
.PHONY 关键字只有标准的make(GNU make)才拥有,在使用非标准的make时可以使用如下技巧定义伪目标。
原理:如果一个规则只有一个目标,并且该目标不是一个存在的文件名,则在执行此规则时,目标总会被认为是最新的。
当执行make clean时,由于 FORCE 会被认为是最新的(FORCE 比 clean 要新),clean 下的命令必然被执行。
#非GNU make下伪目标的实现方法 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 clean : FORCE rm *.o hello.out FORCE :
运行结果:
3. 小结
(1)默认情况下,make 认为目标对应着一个文件
(2) .PHONY 关键字用于声明一个伪目标,伪目标不对应任何实际的文件
(3)伪目标的本质是make中的特殊目标.PHONY的依赖
(4)使用伪目标可以模拟“函数调用”