4.编写规则

Phony Targets

一个伪目标不是一个真正的文件名,只是一个当你明确的运行make请求时会被执行的recipe名字。有两个原因使用伪目标:

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

解决的问题:

clean:
        rm *.o temp

这种写法在没有文件名冲突的时候可以通过make clean正常执行。但是如果在这个目录下有一个同名的文件cleanclean总是会被考虑是最新的文件,它的recipe不会执行。

添加一个伪目标即可解决这个问题:

.PHONY: clean
clean:
        rm *.o temp

与make的递归调用结合使用:

SUBDIRS = foo bar baz

subdirs:
        for dir in $(SUBDIRS); do \
          $(MAKE) -C $$dir; \
        done

这种写法的问题:任何在sub-make中的错误都会被忽视;不能并行构建目标。

改进后的写法:

SUBDIRS = foo bar baz

.PHONY: subdirs $(SUBDIRS)

subdirs: $(SUBDIRS)

$(SUBDIRS):
        $(MAKE) -C $@

foo: baz

最后一句声明了baz完成之后才能构建foo。

对于伪目标将跳过隐含规则的搜索。

伪目标不应该成为一个真实的目标文件的prerequisites,负责每次make更新文件都会执行伪目标的recipe

伪目标也可以有prerequisites

all : prog1 prog2 prog3
.PHONY : all

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

一个伪目标的prerequisites是另一个伪目标时,表现为另一个的子程序:

.PHONY: cleanall cleanobj cleandiff

cleanall : cleanobj cleandiff
        rm program

cleanobj :
        rm *.o

cleandiff :
        rm *.diff

执行顺序:rm *.o -> rm *.diff -> rm program