前言

本文通过简略的几个示例,以及对同一个Makefile进行几个版本的迭代,帮忙疾速的了解变量和模式规定的应用。

1、回顾

在上一篇文章中,咱们应用Makefile编译fun.c和main.c这两个文件,最终生成名为app的可执行文件。

fun.c的内容

#include <stdio.h>void fun(){    printf("This is fun()!\n");}

main.c的内容

extern void fun(); int main(){     fun();     return 0; }

第一版Makefile

.PHONY:cleanall: main.o fun.o    gcc -o app main.o fun.omain.o : main.c     gcc -o main.o -c main.cfun.o : fun.c     gcc -o fun.o -c fun.cclean:    rm app main.o fun.o

能够发现,Makefile外面有很多反复的内容,咱们能够利用变量和模式规定对其进行优化。

2、主动变量

$@:用于示意一个规定中的指标。当有多个指标时,$@指的是其中任何导致规定命令被运行的自标。

$^:示意的是规定中的所有先决条件。

$<:示意的是规定中的第一个先决条件。

是不是看得有点晕?没关系,咱们基于下面的Makefile,做一点点批改,把这些货色都打印进去看一下,就很分明了。

.PHONY:cleanall: main.o fun.o    gcc -o app main.o fun.o        @echo "\$$@ = $@"    @echo "$$^ = $^"    @echo "$$< = $<"    main.o : main.c     gcc -o main.o -c main.cfun.o : fun.c     gcc -o fun.o -c fun.cclean:    rm app main.o fun.o

运行make,终端打印如下内容

gcc -o app main.o fun.o$@ = all$^ = main.o fun.o$< = main.o

理解到这些之后,咱们再次批改

第二版Makefile

.PHONY:cleanall: main.o fun.o    gcc -o app $^    main.o : main.c     gcc -o $@ -c $^fun.o : fun.c     gcc -o $@ -c $^clean:    rm app main.o fun.o

3、变量的类别与赋值

变量的类别有<font color='red'>递归扩大变量</font>和<font color='green'>简略扩大变量</font>

3.1 递归扩大变量

这种只用一个“=”符号定义的变量被称为递归扩大变量

.PHONY:allgoal = $(mid)mid = $(fun)fun = testall:    @echo "goal = $(goal)"

运行make命令 ,打印如下

goal = test

3.2 简略扩大变量

用“:=”操作符来定义的,make只对其进行一次开展。

.PHONY:allgoal_A = hello mid_A  = $(goal_A) worldgoal_A = testgoal_B := hellomid_B  := $(goal_B) worldgoal_B := testall:    @echo "mid_A = $(mid_A),mid_B= $(mid_B)"

运行make命令 ,打印如下

mid_A = test world,mid_B= hello world

3.3 变量条件赋值

用“?=”操作符来定义,如果变量没有被定义,将左边的值赋值给它,如果变量曾经定义了,则不扭转其原值。

.PHONY:allfunA = originalfunA ?= replacementfunB ?= replacementall:    @echo "funA = $(funA),funB = $(funB)"

运行make命令 ,打印如下

funA = original,funB = replacement

3.4 变量追加赋值

通过“+=”实现追加赋值

.PHONY:allobjects = main.o fun.oobjects += append.oall:    @echo "objects = $(objects)"

运行make命令 ,打印如下

objects = main.o fun.o append.o

3.5 高级变量援用性能

在赋值的同时,实现文件名后缀替换操作

.PHONY:allsrc = a.c b.c c.cobjs := $(src:.c=.o)all:    @echo "objs = $(objs)"

运行make命令 ,打印如下

objs = a.o b.o c.o

留神,src:.c=.o 冒号前面不能有空格,如果加了空格变成src: .c=.o ,运行make,打印的后果如下

objs = a.c b.c c.c

4、模式规定

一个模式规定的格局为:

%.o : %.c     command...

咱们利用模式规定对第二版的Makefile进行优化

第三版Makefile

#替换掉这部分#main.o : main.c #    gcc -o $@ -c $^#fun.o : fun.c #    gcc -o $@ -c $^.PHONY:cleanall: main.o fun.o    gcc -o app $^%.o : %.c    gcc -o $@ -c $^clean:    rm app main.o fun.o

这里将两条构建指标文件的规定变成了一条

" % " 相似于通配符,%.c匹配所有以".c "结尾的文件,采纳了模式当前,不论有多少个源文件,都能够用同一条规定,能够极大的简化Makefile

5、利用变量和模式规定优化Makefile

咱们再对第三版的Makefile进行优化,将编译器,指标等都用变量代替,这样当前批改只须要改变变量局部就好了

第四版Makefile

.PHONY:cleanCC = gccRM = rmTARGET = appOBJS = main.o fun.o$(TARGET) : $(OBJS)    $(CC) -o $@ $^%.o : %.c    $(CC) -o $@ -c $^clean:    $(RM) $(TARGET) $(OBJS)

到这里,Makefile曾经失去了很大的改善,然而咱们能够看到OBJS = xxxx 这里,如果文件数量多,得一个个书写,还是不够智能。

下一篇文章,将介绍Makefile函数的应用,利用函数能够轻松治理好源文件和指标文件。
———————————————————————————————

码字不易,点个赞再走吧!

欢送关注我的同名公众号,这里有更多好料等着你哦!