文章目录
一、什么是Makefile
- 一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,
Makefile
文件定义了一系列的规则来指定那些文件需要先编译,那些文件需要后编译,那些文件需要重新编译,甚至于进行更复杂的功能操作,因为Makefile
文件就像一个shell
脚本一样,也可以执行操作系统命令。 Makefile
带来的好处就是“自动化编译”,一旦写好,只需要一个make
命令,整个工程完全自动编译,极大的提高软件开发效率。make
是一个命令工具,是一个解释Makefile
文件中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如 Delphi 的make
,Visual C++ 的nmake
,Linux 下 GUN 的make
。
二、Makefile文件命名、规则和示例
1、文件命名
makefile
或者Makefile
2、Makefile 规则
a. 一个
Makefile
文件中可以有一个或者多个规则
目标 … : 依赖 …
命令(shell命令)
…
目标:最终要生成的文件(伪目标除外)
依赖:生成目标所需要的文件或是目标
命令:通过执行命令对依赖操作生成目标(命令前必须Tab缩进)
b.Makefile
中的其他规则一般都是为第一条规则服务的。
3、示例
实验代码
a、建立并打开 Makefile
文件
nowcode@nowcode:~/test03$ vim Makefile
b、向 Makefile
文件加入一下命令
app:add.c div.c head.h main.c mult.c sub.c
gcc add.c div.c head.h main.c mult.c sub.c -o app
c、使用 make
命令自动编译
nowcode@nowcode:~/test03$ make
gcc add.c div.c head.h main.c mult.c sub.c -o app
nowcode@nowcode:~/test03$ ls
add.c app div.c head.h main.c Makefile mult.c sub.c
nowcode@nowcode:~/test03$ ./app
a = 20, b = 12
a + b = 32
a - b = 8
a * b = 240
a / b = 1.666667
三、工作原理
- 命令执行之前,需要先检查规则中的依赖是否存在
- 如果存在,执行命令
- 如果不存在,向下检查其他的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了,则执行该规则中的命令
- 检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
- 如果依赖的时间比目标的时间晚,需要新生成目标
- 如果依赖的时间比目标的时间早,目标不需要更新,对应规则的命令不需要被执行
- 前面的示例
Makefile
文件可以这样写
app:add.o div.o mult.o sub.o main.o
gcc add.o div.o mult.o sub.o main.o -o app
add.o:add.c
gcc -c add.c -o add.o
div.o:div.c
gcc -c div.c -o div.o
mult.o:mult.c
gcc -c mult.c -o mult.o
sub.o:sub.c
gcc -c sub.c -o sub.o
main.o:main.c
gcc -c main.c -o main.o
四、变量
1、自定义变量
变量名=变量值
var=hello
2、预定义变量
AR : 归档维护程序的名称,默认值为 ar
CC : C编译器的名称,默认值为 gcc
CXX : C++编译器的名称,默认值为 g++
$@ : 目标的完整名称
$< : 第一个依赖文件的名称
$^ : 所有的依赖文件
3、获取变量的值
$(变量)
$(var)
注意:自动变量只能在规则的命令中使用
app:add.o div.o main.o mult.o sub.o
gcc add.o div.o main.o mult.o sub.o -o app
以上的语句可以用以下语句替换
app:add.o div.o mult.o sub.o main.o
$(CC) $^ -o $@
五、模式匹配
%.o:%.c
% : 通配符,匹配一个字符串
两个%匹配的是同一个字符串
add.o:add.c
gcc -c add.c -o add.o
div.o:div.c
gcc -c div.c -o div.o
mult.o:mult.c
gcc -c mult.c -o mult.o
sub.o:sub.c
gcc -c sub.c -o sub.o
main.o:main.c
gcc -c main.c -o main.o
以上的语句可以用以下语句替换
%.o:%.c
gcc -c $< -o $@
六、函数
1、$(wildcard PATTERN…)
- 功能:获取指定目录下指定类型的文件列表
- 参数:PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔
- 返回:得到的若干文件的文件列表,文件名之间使用空格间隔
- 示例:
$(wildcard *.c ./sub/*.c)
返回值格式:a.c b.c c.c d.c e.c f.c
2、$(parsubst < pattern >, < replacement >, < text >)
- 功能:查找
<text>
中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是符合模式<pattern>
,如果匹配的话,则以<replacement>
替换。 <pattern>
可以包括通配符‘%’,表示任意长度的字符串。如果<replacement>
中也包含‘%’,那么,<replacement>
中的这个‘%’将是<pattern>
中的那个‘%’所代表的字符串。(可以用‘\’来转义,以’%‘来表示真实含义的‘%’字符串)- 返回:函数返回被替换过后的字符串
- 示例:
$(patsubst %.c, %.o, x.c bar.c)
返回值格式:x.o bar.o
上面实验(第二的示例)可以用以下代码实现
# 获取所有的.c文件
src=$(wildcard ./*.c) # src的值为 add.c div.c head.h main.c mult.c sub.c
# 将.c文件替换.o文件
objs=$(patsubst %.c, %.o, $(src)) # objs的值为 add.o div.o main.o mult.o sub.o
target=app
$(target):$(objs)
$(CC) $^ -o $@
%.o:%.c
$(CC) -c $< -o $@
七、删除.o文件
使用 make
命令自动编译后,文件夹中会多了 .o
文件
nowcode@nowcode:~/test03$ vim Makefile
nowcode@nowcode:~/test03$ make
cc -c mult.c -o mult.o
cc -c main.c -o main.o
cc -c add.c -o add.o
cc -c div.c -o div.o
cc -c sub.c -o sub.o
cc mult.o main.o add.o div.o sub.o -o app
nowcode@nowcode:~/test03$ ls
add.c add.o app div.c div.o head.h main.c main.o Makefile mult.c mult.o sub.c sub.o
在 Makefile
文件中加入下面语句
.PHONY:clean
clean:
rm $(objs) -f
加入后执行以下命令就可以将所有 .o
文件删除
nowcode@nowcode:~/test03$ make
make: “app”已是最新。
nowcode@nowcode:~/test03$ make clean
rm ./add.o ./mult.o ./main.o ./div.o ./sub.o -f
nowcode@nowcode:~/test03$ ls
add.c app div.c head.h main.c Makefile mult.c sub.c