上次提到了伪目标、变量及函数
先说说伪目标 与 变量: 函数不多但用法很灵活 换句话说就是 太复杂了 以后慢慢讨论
先看一个例子:
OBJS = main.o a.o b.o
main: $(OBJS)
cc -o main $(OBJS)
main.o: main.h
a.o: a.h
b.o: b.h
.PHONY: clean
clean:
rm -f main $(OBJS)
伪目标就是以关键字.PHONY开头的,表示clean是一个为目标,因为我们并不会去生成一个clean文件,所以伪目标并不是一个文件而是一个标签,既然在编译时生成了一下目标文件与可执行文件,就应该可以将他们都删除(make clean)以便重新编译,
OBJS = main.o a.o b.o .PHINY: all all:main main: $(OBJS) cc -o main $(OBJS) main.o: main.h a.o: a.h b.o: b.h .PHONY: clean clean: rm -f main $(OBJS)如果将Makefile写成这样就可以使用make all 编译全部 make clean 删除中间件以及生成的可执行文件,这也是写Makefile的一般规则 当然可以有更所的伪目标根据项目需要
FOO = $(PHELLO) PHELLO = $(HELLO) HELLO = hello all: echo $(FOO)
make all 时候会打印出hello出来, 这样看起来 变量的声明是不需要一定顺序的 ,但是看起来很费劲, 你得FOO引用到PHELLO 而PHELLO在FOO下面定义,这样如果一个定义引用到隔着n多行的定义 看起来就没那么容易了
为了避免上边的问题,make中使用另一种变量定义方法这样他前面的变量不能使用后面的变量
X := main.c Y := $(X) a.c Z := $(Y) b.c
Z的值是main.c a.c b.c
而如果这样:
Z := $(Y) b.c Y := $(X) a.c X := main.c那么Z的值也就是 b.c 因为在Z上面没有定义Y所以默认Y就是空
上面是比较简单的例子看一个带MAKELEVEL的(这是指当make嵌套的层数)
ifeq ($(MAKELEVEL), 0) CUR_DIR := $(shell pwd) WHOAMI := $(shell whoami) HOST_TYPE := $(shell arch) endifFOO ?= bar 等价于 ifeq($(origin FOO), undefined) FOO = bar endif
?=表示在此变量没有定义事对变量赋值,如果变量已经定义了则此句无效
追加变量值
OBJS = main.o a.o b.o OBJS += c.o OBJS展开后就是main.o a.o b.o c.o