一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个日录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个she!本一样,其中也可以执行操作系统的命令。
Makefile带来的好处就是--"自动化编译",一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefle中指令的命令工具,一般来说,大多数的IDE都有这个命令。
make主要解决两个问题:
1)大量代码的关系维护
大项日中源代码比较多,手丁维护、编译时间长而目编译命令复杂,难以记忆及维护把代码维护命令及编译命令写在makefile文件中,然后再用make工具解析此文件自动执行相应命令,可实现代码的合理编译。
2)减少重复编译时间
在改动其中一个文件的时候,能判断哪些文件被修改过,可以只对该文件进行軍新编译,然后重新接所有的目际文件,节省编译时间。
Makefile语法规则
一条规则
目标:依赖文件列表
<tab>命令列表
Makefile基本规则三要素:
1)目标:
- 通常是要产生的文件名称,目标可以是可执行文件或其它ob文件,也可是一个动作的名称
2)依赖文件
- 用来输入从而产生日标的文件
- 一个日标通常有几个依赖文件(可以没有)
3)命令
- make执行的动作,一个规则可以含几个命令(可以没有)
- 有多个命令时,每个命令占一行
make命令格式
make是一个命令工具,它解释Makefile 中的指令(应该说是规则)。
make命令格式:
make[-f file][options][target]
1.[-f file]:
- make默认在工作日录中寻找名为GNUmakefile、makefile、Makefile的文件作为Makefile输入文件
- -f可以指定以上名字以外的文件作为makefle输入文件
2.[options]
- -v:显示make工具的版本信息
- -w:在处理makefile之前和之后显示工作路径
- -C dir:读取makefile之前改变工作路径至dir目录
- -n:只打印要执行的命令但不执行
- -s:执行但不显示执行的命令
3.[targets]
- 若使用make命令时没有指定日标,则make工具默认会实现makefile文件内的第一个日标,然后退出
- 指定了make工具要实现的目标,目标可以是一个或多个(多个目标间用空格隔开)。
Makefile工作原理
1)若想生成目标,检查规则中的依赖条件是否存在,如不存在,则寻找是否有规,则用来 生成该依赖文件
2)检查规则中的日标是否需要更新,必须先检査它的所有依軌,依赖中有任一个被更新,则目标必须更新
Makefile简单举例
最简单的Makefile:
test:add.c sub.c mul.c div.c test.c
gcc add.c sub.c mul.c div.c -o test
修改之后的Makefile:
test:add.o sub.o mul.o div.o test.o
gcc add.o sub.o mul.o div.o test.o -o test
add.o:add.c
gcc -c add.c -o add.o
sub.o:sub.c
gcc -c sub.c -o sub.o
mul.o:mul.c
gcc -c mul.c -o mul.o
div.o:div.c
gcc -c div.c -o div.o
test.o:test.c
gcc -c test.c -o test.o
Makefile中的变量
在Makefie中使用受量有点类似于C语言中的宏定义,使用该变量量相当于内容替换,使用变量可以使Makefile易于维护,修改内容变得简单。
自定义变量
1)定义变量方法:
交量名=交星值
2)引用变量
$[变量名] or $(变量名)
3)Makefile的变量名
- makefike变量名可以以数字开头
- 交量是大小写敏感的
- 交量一般都在makefike的头部定义
- 交量几乎可在makefike的任何地方使用
使用变量替代目标文件
OBJS = add.o sub.o mul.o div.o test.o
test:$(OBJS)
gcc $(OBJS) -o test
add.o:add.c
gcc -c add.c -o add.o
sub.o:sub.c
gcc -c sub.c -o sub.o
mul.o:mul.c
gcc -c mul.c -o mul.o
div.o:div.c
gcc -c div.c -o div.o
test.o:test.c
gcc -c test.c -o test.o
clean:
rm -rf $(OBJS) test
系统提供
除了使用用户自定义安量,makefile中也提供了一些变量(变量名大写)供用户直接使用,我们可以直接对其进行赋值。
CC = gcc #arm-linux-gcc
CPPFLAGS #C预处理选项 如-l
CFLAGS #C编译器选项-wall-g-c
LDFLAGS #连接器选项-L -l
模式规则
模式规则示例:
%.o:%.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
使用模式规则的示例:
OBJS = add.o sub.o mul.o div.o test.o
TARGET = test
#这些变量不能单独使用必须在命令中使用
#$@ 表示目标
#$^ 表示所有依赖
#$< 表示第一个依赖:wq
$(TARGET):$(OBJS)
gcc $^ -o $@
#模式匹配 所有的.o都依赖对应的.c
#将所有的.c生成对应的.o
%.o:%.c
gcc -c $< -o $@
clean:
rm -rf $(OBJS) $(TARGET)
Makefile中的函数
makefile中的函数有很多,在这里给大家介绍两个最常用的。
- wildcard-查找指定目录下的指定类型的文件
src = $(wildcard *,c) //找到当前目录下所有后缀为.c的文件,赋值给src - patsubst-匹配替换
obj = $(patsubst %.c,%.o,$(src)) /把src变量里所有后缀为.c的文件替换成.o
在Makefile中所有函数都是有返回值的。
示例如下:
#获取当前目录下所有的.c文件
SRC = $(wildcard ./*.c)
#将SRC中所有出现.c的替换成.o
OBJS = $(patsubst %.c, %.o, $(SRC))
TARGET = test
#这些变量不能单独使用必须在命令中使用
#$@ 表示目标
#$^ 表示所有依赖
#$< 表示第一个依赖:wq
$(TARGET):$(OBJS)
gcc $^ -o $@
#模式匹配 所有的.o都依赖对应的.c
#将所有的.c生成对应的.o
%.o:%.c
gcc -c $< -o $@
#声明clean为为伪目标 伪目标不去判断目标文件是否存在或者已经更新
#无条件执行命令
.PHONY:clean
clean:
rm -rf $(OBJS) $(TARGET)
Makefile中的伪目标
clean用途: 清除编译生成的中间.0文件和最终目标文件
make clean 如果当前目录下有同名clean文件,则不执行clean对应的命令,解决方案:
伪目标声明:.PHONY:clean
声明目标为伪目机之后,makefle将不会该判断目标是杏存在或者该目标是否需要更新
clean命令中的特殊符号:
- "-" 此条命令出错,make也会继续执行后续的命令。如:“-rm main.o”
- “@"不显示命令本身,只显示结果。如:"@echo clean done'