make和Makefile总结二

该系列将会一步一步的从最基本的Makefile文件编写讲到复杂项目的Makefile编写


一:最基本的编译多文件的Makefile编写

编写Makefile的第一步,不是一个猛子扎进去试着写一个规则并对之调试,
而应先采用面向依赖关系的思考方法勾勒出Makefile要表达怎样的依赖关系,
这一点至关重要。通过不断地练习这种思考方法,才可能达到流畅地编写Makefile。

假如我们现在有这么一个项目:mian.c 和 fun.c
mian.c中有用到fun.c中定义的函数
我们第一反应的依赖关系应该是:
main 依赖于 main.c 和 fun.c

但这样的依赖关系,在现实的项目中,会使Makefile的可维护性很差,我们
应该让依赖关系尽可能详细当也不能太复杂
所以就有下面这样的依赖关系:
main 依赖于 main.o 和 fun.o
mian.o 依赖于 main.c
fun.o 依赖于 fun.c

也就可以写出下面这段Makefile

main:mian.o fun.o
		gcc -o main main.o fun.o
mian.o:main.c
	gcc -o main.o -c main.c
fun.o:fun.c
	gcc -o fun.o -c fun.c
.PHONY:clean
clean:
	rm fun.o main.o main
  • 这样最基本的编译多文件的Makefile文件就写好了

二:使用变量,提高Makefile的可维护性

.PHONY:clean
CC = gcc
RM = rm

EXE = main
OBJS = main.o fun.o

$(EXE):$(OBJS)
	$(CC) -o $(EXE) $(OBJS)
mian.o:main.c
	$(CC) -o main.o -c main.c
fun.o:fun.c
	$(CC) -o fun.o -c fun.c
clean:
	$(RM) $(EXE) $(OBJS)

我们引入了CC,RM,EXE,OBJS四个变量,使用变量时采用$(变量名) 或 ${变量名}

或许对于这个项目来说使不使用变量都感觉差不多,但是在更一点的项目中变量就能起很大的作用了


三:自动变量

在Makefile经常会存在目标名和先决条件名在规则的命令中重复出现。
如果目标名或先决条件名发生了改变,那得在相应的命令中跟着改,这很麻烦。
为了省去这种麻烦,我们可以借助如下一些自动变量。

自动变量说明
$@用于表示一个规则中的目标。当一个规则中有多个目标时,$@所指的是其中任何造成规则命令被运行的目标。
$^表示的是规则中的所有先决条件
$<表示的是规则中的第一个先决条件
$%当目标文件是一个静态库文件时,代表静态库的一个成员名
$?所有比目标文件更新的依赖文件列表,空格分隔。如果目标文件时静态库文件,代表的是库文件(.o 文件)
$+类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合
$*在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的部分(当文件名中存在目录时,“茎”也包含目录部分)

一般我常用的自动变量就前3个

还有两个特殊的变量:MAKE和MAKECMDGOALS
$(MAKE):就是当前处理Makefile的命令是什么,一般是就是make
$(MAKECMDGOALS):当前构建的目标名


四:变量的定义和赋值

1.递归扩展变量:只用"="来赋值的

例如:
name = $(ch) -o
ch = $(gd)
gd = sz

最后使用$(name)就是sz -o
如果是name = $(name) -o,就会形成一个死循环

2.简单扩展变量:就是使用":="来赋值的

例如:
name := $(ch) -o
ch := $(gd)
gd := sz

最后使用$(name)就是 -o

可以自行试一下下面这个例子来看看输出:
.PHONY:all
x=foo
y=$(x) b x-later

xx:=foo
yy:=$(xx)b xx*later

all:
	@echo"x=$(y),xx=$(yy)"

3.判断赋值:“?=”,使用?=时然后变量之前没有定义就赋值,如果已经定义就不赋值

4.追加赋值:“+=”,就是在变量原本的值后面继续追加值

5.变量的值不仅是从Makefile文件中的定义获取,还可以来自shell环境中定义的变量

make_name ?= make_name
all:
	@echo "make_name:$(make_name)"

先直接make看看这个段Makefile会输出什么
再先在shell上运行export make_name=111,然后再make看看会输出什么

6.引用变量的高级用法:

source = main.c fun.c fun2.c
objs = $(source:.c=.o)

这时候$(objs)就是main.o fun.o fun2.o

7.避免变量被覆盖的方法:

	使用override name = xxx,这样后面就修改不了变量了

五:借助"模式"来精简规则

如果我们的项目有很多个.c文件,那每一个.c文件都要手动加一个规则来生成.o文件,那就太麻烦了
我们可以使用通配符来简化这一操作
就可以将上面第二点中的Makefile简化成这样:

.PHONY:clean
CC = gcc
RM = rm

EXE = main
OBJS = main.o fun.o

$(EXE):$(OBJS)
	$(CC) -o $(EXE) $(OBJS)
	
%.o:%.c
	$(CC) -o $@ -c $^

clean:
	$(RM) $(EXE) $(OBJS)

  • 这样Makefile文件又更进一步了
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值