Makefile中.PHONY的作用是什么
Makefile中.PHONY的作用是什么
技术背景
在Makefile里,默认的目标是“文件目标”,也就是用于从其他文件构建新文件。Make默认其目标是一个文件,这让编写Makefile变得相对容易。不过,有时我们希望Makefile执行的命令并不对应文件系统中的物理文件,像常见的“clean”和“all”目标就是如此。
实现步骤
未使用.PHONY的情况
假设在Makefile里有如下规则:
1 |
|
要是当前目录下存在名为clean
的文件,当执行make clean
时,Make会认为该目标与这个文件关联,只有当文件相对于其依赖项看起来不是最新时,才会执行相应命令。若文件已存在且依赖项未改变,Make就不会执行rm -rf *.o
命令。
使用.PHONY的情况
在Makefile中添加.PHONY
声明:
1 |
|
这样,即便存在名为clean
的文件,执行make clean
时,Make也会忽略该文件,直接执行rm -rf *.o
命令。
核心代码
示例1:基本的.PHONY使用
1 |
|
示例2:多个.PHONY目标
1 |
|
示例3:使用::
声明伪目标
1 |
|
最佳实践
一般而言,Makefile中所有不会生成与目标同名输出文件的目标都应声明为伪目标。常见的伪目标有all
、install
、clean
、distclean
等。例如:
1 |
|
常见问题
伪目标依赖关系的问题
当一个物理目标依赖于伪目标,而伪目标又依赖于另一个物理目标时,可能会出现意外情况。比如:
1 |
|
在这个例子中,fileall
通过伪目标间接依赖于file1
,由于伪目标总是被视为更新过,所以fileall
总会被重新构建。若将fileall
的依赖从filefwd
改为file1
,则fileall
仅在依赖目标相对于它过期时才会被重新构建。
目标捕获规则的问题
在Makefile中使用目标捕获规则时,伪目标的声明会影响规则的执行。例如:
1 |
|
若未声明superclean
为伪目标,执行make superclean
时,会触发clean
、andsomethingelse
和catcher superclean
;声明后,make superclean
就不会触发catcher superclean
。