Makefile
什么是Makefile
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,Makefile文件定义了一系列的规则来指定哪些文件需要先编译,那些文件需要后编译,那些文件需要重新编译,甚至于进行更复杂的功能操作,因为Makefile文件就像一个Shell脚本一样,也可以执行操作系统的命令。
Makefile带来的好处就是“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释Makefile文件中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如Delphi的 make,Visual C++的nmake,Linux下GNU的make。
文件命名
makefile 或者 Makefile
◼ Makefile 规则
一个 Makefile 文件中可以有一个或者多个规则
目标 ...: 依赖 ...
命令(Shell 命令)
...
⚫ 目标:最终要生成的文件(伪目标除外)
⚫ 依赖:生成目标所需要的文件或是目标
⚫ 命令:通过执行命令对依赖操作生成目标(命令前必须 Tab 缩进)
Makefile 中的其它规则一般都是为第一条规则服务的。
案例:当前目录文件夹有 add.c div.c head.h main.c mult.c sub.c 文件
vim Makefile文件进行编辑:
app:sub.c add.c mult.c div.c main.c gcc sub.c add.c mult.c div.c main.c -o app
Esc + :wq 保存退出
生成Makefile文件后,对文件中各依赖文件(add.c div.c main.c mult.c等其他)进行修改后,仅需要键入 make 即可重新编译生成可执行文件 提高简便性
工作原理:
◼ 命令在执行之前,需要先检查规则中的依赖是否存在
如果存在,执行命令
如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了,则执行该规则中的命令
1 app:sub.o add.o mult.o div.o main.o 2 gcc sub.o add.o mult.o div.o main.o -o app 3 sub.o:sub.c 4 gcc -c sub.c -o sub.o 5 add.o:add.c 6 gcc -c add.c -o add.o 7 mult.o:mult.c 8 gcc -c mult.c -o mult.o 9 div.o:div.c 10 gcc -c div.c -o div.o 11 main.o:main.c 12 gcc -c main.c -o main.o
3-12语句执行完后,执行1-2
长语句(1-12 .o )相较短语句( .c )当某个文件更改后,仅编译更改的文件,并链接, 短语句会将每个文件都重新编译并链接,长语句效率编译效率更高。
◼ 检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
如果依赖的时间比目标的时间晚,需要重新生成目标
如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行
变量:
◼ 自定义变量
变量名=变量值 var=hello
◼ 预定义变量
AR : 归档维护程序的名称,默认值为 ar
CC : C 编译器的名称,默认值为 cc
CXX : C++ 编译器的名称,默认值为 g++
$@ : 目标的完整名称
$< : 第一个依赖文件的名称
$^ : 所有的依赖文件
◼ 获取变量的值
$(变量名) 获取:$(var)
app:main.c a.c b.c
gcc -c main.c a.c b.c
#自动变量只能在规则的命令中使用
app:main.c a.c b.c
$(CC) -c $^ -o $@
模式匹配
add.o:add.c
gcc -c add.c
div.o:div.c
gcc -c div.c
sub.o:sub.c
gcc -c sub.c
mult.o:mult.c
gcc -c mult.c
main.o:main.c
gcc -c main.c
匹配替换
%.o:%.c
- %: 通配符,匹配一个字符串
- 两个%匹配的是同一个字符串
%.o:%.c
gcc -c $< -o $@
函数
◼ $(wildcard PATTERN...)
功能:获取指定目录下指定类型的文件列表
参数:PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔
返回:得到的若干个文件的文件列表,文件名之间使用空格间隔
示例:
$(wildcard *.c ./sub/*.c)
返回值格式: a.c b.c c.c d.c e.c f.c
◼ $(patsubst <pattern>,<replacement>,<text>)
功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。
<pattern>可以包括通配符`%`,表示任意长度的字串。如果<replacement>中也包含`%`,
那么,<replacement>中的这个`%`将是<pattern>中的那个%所代表的字串。(可以用`\`来转义,以`\%`来表示真实含义的`%`字符)
返回:函数返回被替换过后的字符串
示例:
$(patsubst %.c, %.o, x.c bar.c) 将 x.c bar.c 由.c 替换为 .o
返回值格式: x.o bar.o
此时外部目录创建 clean文件后,由于依赖文件 clean: 为空 因此系统总认为文件最新 不执行指令
可以在Makefile中将clean设置为伪目标 就不会生成特定文件 不会与外部文件 clean进行对比 make clean 正常执行
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)