欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

GNU Make工具(二)Phony Targets

程序员文章站 2022-07-14 15:24:44
...

Phony Targets

上一篇提到了makefile基本的rule如下:

Here is what a simple rule looks like:

target:   dependencies ...
          commands
          ...

A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request. There are two reasons to use a phony target: to avoid a conflict with a file of the same name, and to improve performance.

Phony Target的引入是为了解决某些特定问题的。Phony Target是一系列命令的标识,可以想成是函数名,标号之类。

  • 避免同名文件的冲突
  • 提升性能

The implicit rule search (see Implicit Rules) is skipped for .PHONY targets. This is why declaring a target as .PHONY is good for performance, even if you are not worried about the actual file existing.

例如很常见的make clean命令

clean:
	rm *.o temp
	...

使用上面的写法,假如目录下没有叫clean的文件并且command中也没有生成target的命令,那么每次执行make clean命令,clean都会被执行,符合我们的预期。但是如果目录下有一个叫clean的文件存在或者被生成,那么clean之后的指令将得不到执行。因为clean是一个target却没有依赖,所以它始终被make工具认为是最新的,所以不会被更新,其定义的command也就不会被执行。

为了解决上述问题,我们可以显式地声明target为phony类型,.PHONY是make内建的特殊目标名。

.PHONY: clean
clean:
        rm *.o temp

如此一来,make clean定义的命令无论目录下是否存在名叫clean的文件都会被执行。

Phony的其他用法

make的递归使用

大型系统构建时通常会包含很多子目录,我们可以在主目录的makefile中执行命令切换到子目录然后调用make命令来完成子目录的构建。

subsystem:
       cd subdir && $(MAKE)

#上述命令等价于
subsystem:
   		$(MAKE) -C subdir

#同样可以声明为phony对象
.PHONY: subsystem subdir
subsystem: subdir
subdir:
   		$(MAKE) -C [email protected]

Phony使用规则

phony target通常不作为其他real target的依赖,否则当real target被更新时phony target对应的命令每次都会被执行;
对于make clean而言,我们是保证clean对象不会作为real target的依赖,所以只有显式调用的时候才会执行;
phony target可以有相应的依赖,这个依赖可以是 phony target,也可以是real target;

.PHONY : all
all : prog1 prog2 prog3

prog1 : prog1.o utils.o
        cc -o prog1 prog1.o utils.o

prog2 : prog2.o
        cc -o prog2 prog2.o

prog3 : prog3.o sort.o utils.o
        cc -o prog3 prog3.o sort.o utils.o

如果phony target的依赖也是phony target,那么被依赖的phony target会作为一个subroutine被执行。

.PHONY: cleanall cleanobj cleandiff

cleanall : cleanobj cleandiff
        rm program

cleanobj :
        rm *.o

cleandiff :
        rm *.diff