目录
2.检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间。
一 、Makefile是什么
1.对Makefile的理解
如图所示,一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中, Makefile 文件定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 Makefile 文件就像一个 Shell 脚本一样,也可以执行操作系统的命令。
2.Makefile的优点和使用
Makefile 带来的好处就是自动化编译,一旦写好,只需要一个 make 命令,整 个工程完全自动编译,极大的提高了软件开发的效率。make 是一个命令工具,是一个 解释 Makefile 文件中指令的命令工具,一般来说,大多数的 IDE 都有这个命令, 比如 Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的 make。
二 、Makefile 文件命名和规则
1.文件命名
makefile或者Makefile
2.Makefile 文件内容的书写规则
一个 Makefile 文件中可以有一个或者多个规则,此外,Makefile 中的其它规则一般都是为第一条规则服务的。
目标 ...: 依赖 ...
命令(Shell 命令)
...
目标:最终要生成的文件,伪目标除外。
依赖:生成目标所需要的文件或是目标。
命令:通过执行命令对依赖操作生成目标,命令前必须 Tab 缩进。
3.示例
两种书写方法,可以分开写,也可以写在一起。
test:a.c b.c d.c e.c main.c
gcc a.c b.c d.c e.c main.c -o test
test:a.o b.o d.o e.o main.o
gcc a.o b.o d.o e.o main.o -o test
a.o:a.c
gcc -c a.c -o a.o
b.o:b.c
gcc -c b.c -o b.o
d.o:d.c
gcc -c d.c -o d.o
e.o:e.c
gcc -c e.c -o e.o
main.o:main.c
gcc -c main.c -o main.o
三 、Makefile 工作原理
1.命令在执行之前,需要先检查规则中的依赖是否存在。
(1)如果存在,执行命令。
(2)如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了,则执行该规则中的命令。
2.检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间。
(1)如果依赖的时间比目标的时间晚,需要重新生成目标。
(2)如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行。
test:a.o b.o d.o e.o main.o
gcc a.o b.o d.o e.o main.o -o test
a.o:a.c
gcc -c a.c -o a.o //如果对a.c文件进行了修改,检测到依赖更新时间晚则该命令会重新执行。
b.o:b.c
gcc -c b.c -o b.o
d.o:d.c
gcc -c d.c -o d.o
e.o:e.c
gcc -c e.c -o e.o
main.o:main.c
gcc -c main.c -o main.o
四 、使用变量简化Makefile写法
1.自定义变量
变量名=变量值 var=hello
2.预定义变量
AR : 归档维护程序的名称,默认值为 ar
CC : C 编译器的名称,默认值为 cc
CXX : C++ 编译器的名称,默认值为 g++
$@ : 目标的完整名称
$< : 第一个依赖文件的名称
$^ : 所有的依赖文件
3.获取变量的值
$(变量名)
$(var)
4.示例
//定义变量简化makefile的写法
//test:a.o b.o d.o e.o main.o
// gcc a.o b.o d.o e.o main.o -o test
src=a.o b.o d.o e.o main.o
target=test
$(target):$(src)
$(CC) $(src -o $(target) //变量用法
a.o:a.c
gcc -c a.c -o a.o
b.o:b.c
gcc -c b.c -o b.o
d.o:d.c
gcc -c d.c -o d.o
e.o:e.c
gcc -c e.c -o e.o
main.o:main.c
gcc -c main.c -o main.o
五、Makefile的模式匹配
1.模式匹配规则
使用变量简化makefile的写法貌似也没有很简单的很明显,下面使用模式匹配继续写。
%.o:%.c
-%: 通配符,匹配一个字符串
- 两个%匹配的是同一个字符串
%.o:%.c
gcc -c $< -o $@
//使用模式匹配进行makefile书写简化
//test:a.o b.o d.o e.o main.o
// gcc a.o b.o d.o e.o main.o -o test //原始写法
src=a.o b.o d.o e.o main.o
target=test
$(target):$(src)
$(CC) $(src) -o $(target) //变量用法
%.o:%.c
$(CC) -c $< -o $@ //模式匹配用法
//a.o:a.c
// gcc -c a.c -o a.o
//b.o:b.c
// gcc -c b.c -o b.o
//d.o:d.c
// gcc -c d.c -o d.o
//e.o:e.c
// gcc -c e.c -o e.o
//main.o:main.c
// gcc -c main.c -o main.o
六、函数
1.$(wildcard PATTERN...)
(1)功能:
获取指定目录下指定类型的文件列表。
(2)参数
PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔。
(3)返回
得到的若干个文件的文件列表,文件名之间使用空格间隔。
(4)示例
$(wildcard *.c ./sub/*.c) 返回值格式: a.c b.c c.c d.c e.c f.c
//函数用法1
//src=a.o b.o d.o e.o main.o
src=$(wildcard ./*.c)
target=test
$(target):$(src)
$(CC) $(src) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
2.$(patsubst <pattern>,<replacement>,<text>)
(1)功能:
查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。
(2)参数
<pattern>可以包括通配符`%`,表示任意长度的字串。如果<replacement>中也包含`%`,那么,<replacement>中的这个'%`将是中的那个'% '所代表的字串。(可以用`\`来转义,以`\%`来表示真实含义的`%`字符)。
(3)返回
函数返回被替换过后的字符串。
(4)示例
$(patsubst %.c, %.o, x.c bar.c)
返回值格式: x.o bar.o
//函数用法2
//src=a.o b.o d.o e.o main.o
src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src)) //函数应用
target=test
$(target):$(objs)
$(CC) $(objs) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
3.使用clean删除多余的.o文件
//clean掉多余.o文件
//src=a.o b.o d.o e.o main.o
src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src))
target=test
$(target):$(objs)
$(CC) $(objs) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
.PHONY:clean //变为伪目标文件 防止出现依赖检查更新 从而无法运行clean
clean
rm $(objs) -f