news 2026/4/18 9:19:33

Makefile入门

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Makefile入门

一、基本原理

Makefile 是由工具 make 使用的配置文件。make 会读取 Makefile 中的内容,根据定义的规则和依赖关系来构建目标文件。

make 工作方式:

1.查找目标文件是否存在。

2.如果目标文件不存在,或者其依赖文件的修改时间比目标文件更新,则执行相应的命令生成目标文件。

二、基本语法

target: dependencies command

target:生成的目标文件或目标名称

dependencies:生成目标文件所依赖的文件名称

command:生成目标文件的命令,必须以Tab开头

三、实践出真知

以此目录结构下的文件做测试,将逐步深入介绍。

1、自定义变量

使用自定义变量:(优先使用海象运算符:=。2025.09.03更新了内容)

# 使用 = VAR1 = hello VAR2 = $(VAR1) VAR1 = world # 最终 VAR2 的值是 world,因为 VAR1 在使用时才展开 # 使用 := VAR1 := hello VAR2 := $(VAR1) VAR1 := world # 最终 VAR2 的值是 hello,因为 VAR1 在定义 VAR2 时已经展开了
# 自定义变量 target = main dep = add.o sub.o main.o # 使用$()获取变量 $(target):$(dep) g++ $(dep) -o $(target) add.o: g++ -c add.cpp -o add.o sub.o: g++ -c sub.cpp -o sub.o main.o: g++ -c main.cpp -o main.o clean: rm $(dep) $(target)

1.执行 make 时不指定目标名称,默认执行第一个目标。

2.当依赖文件不存在,make 会根据已有规则尝试构建。make 找不到规则,则执行错误。

3.一般目标名称不能为空,它指引着 make 的操作。

4.依赖名称可以为空,命令中指定着所需要的依赖文件。

运行情况如下:

2、内置变量

CXX 默认 g++,指定c++编译器。

CC 默认 cc,指定c编译器。

RM 默认 rm -f, 删除文件命令。

...

使用内置变量:

target = main dep = add.o sub.o main.o $(target):$(dep) $(CXX) $(dep) -o $(target) add.o: $(CXX) -c add.cpp -o add.o sub.o: $(CXX) -c sub.cpp -o sub.o main.o: $(CXX) -c main.cpp -o main.o clean: $(RM) $(dep) $(target)

如果自定义变量名与内置变量名重复,优先使用自定义变量。

3、自动变量

$@:表示目标文件名称,包含文件扩展名。

$^:依赖项中,所有不重复的依赖文件。

$<:依赖项中第一个依赖文件名称。

...

使用自动变量:

# 自定义变量 target = main dep = add.o sub.o main.o # 自定义变量覆盖内置变量 CXX = g++ $(target):$(dep) $(CXX) $^ -o $@ #使用自动变量 add.o: $(CXX) -c add.cpp -o add.o sub.o: $(CXX) -c sub.cpp -o sub.o main.o: $(CXX) -c main.cpp -o main.o clean: $(RM) $(dep) $(target)

4、模式匹配

%:通配符。

使用模式匹配:

# 自定义变量 target = main dep = add.o sub.o main.o # 自定义变量覆盖内置变量 CXX = g++ $(target):$(dep) $(CXX) $^ -o $@ # 使用自动变量 %.o:%.cpp # 使用模式匹配,将所有.cpp文件编译为.o文件 $(CXX) -c $< -o $@ clean: $(RM) $(dep) $(target)

1. * 通常用于文件名匹配或 wildcard 函数中,表示任意数量的字符。

2. % 用于模式规则中,表示一个模式中的任意字符串,用于定义通用的构建规则。

5、函数

使用方式:$(函数名 参数1,参数2...),多参数使用逗号隔开。

wildcard <pattern...>:只有一个参数,指定某个或多个目录下的某种类型文件,多个目录使用空格隔开。返回所匹配的文件列表。

patsubst <pattern>,<replacement>,<text>:将 <text> 中匹配 <pattern> 的部分替换为<replacement>。

...

使用函数:

# 自定义变量 target = main obj = $(wildcard *.cpp) # 使用wildcard函数找到匹配的文件 dep = $(patsubst %.cpp, %.o, $(obj)) # 使用patsubst函数对内容替换 # 自定义变量覆盖内置变量 CXX = g++ $(target):$(dep) $(CXX) $^ -o $@ # 使用自动变量 %.o:%.cpp # 使用模式匹配 $(CXX) -c $< -o $@ clean: $(RM) $(dep) $(target)

结果展示:

6、使用.PHONY

假设在项目文件夹内有一个文件名称和 Makefile 中的目标名称一致,在使用 make 构建项目时,make 会认为这个目标文件已被构建完成而不继续执行命令。对于一些目标名称只是表示一些动作或任务时,这并不会产生目标文件。那么这时候就会有冲突。

此时我们就可以使用 .PHONY 来告诉 make 这些目标文件是虚拟的,不应该被视为文件。

此时我们自己创建了一个文件名为 clean 的文件,可以发现当我们使用 make clean 指令时,并没有按预期执行命令,而是提示"clean"已是最新。

使用 .PHONY:

# 自定义变量 target = main obj = $(wildcard *.cpp) # 使用wildcard函数找到匹配的文件 dep = $(patsubst %.cpp, %.o, $(obj)) # 使用patsubst函数对内容替换 # 自定义变量覆盖内置变量 CXX = g++ $(target):$(dep) $(CXX) $^ -o $@ # 使用自动变量 %.o:%.cpp # 使用模式匹配 $(CXX) -c $< -o $@ .PHONY:clean clean: $(RM) $(dep) $(target)

结果展示:

7、Tips

make -j4

-j:表示 jobs;

4:表示同时运行 4 个编译任务。

make 会分析 Makefile 中的依赖关系,若多个目标文件无相互依赖,则同时编译。数字参数可依据 CPU 核心改变,使得编译任务并行提高效率。

四、深入Makefile

1、目标名称和依赖项说明

target: dependencies command

我们知道真正的命令执行在于 command 部分,即使目标名称 target 和 依赖项 dependencies 发生变化,只要 command 正确。依旧可以正确执行。

但并不能忽视target : dependencies,因为目标名称和依赖项会被 make 监控,一旦这两项中的文件发生改变,make 会监控到并做出改变。

例如,当依赖文件发生改变时我们可以继续执行 make 命令编译出新文件。如果没有改变,则会提示目标文件已是最新,不会执行命令。再者,目标名称,在实际开发中我们应该保持命令中最终生成的可执行文件名称与目标名称 target 一致。这是因为如果不一致,make 命令的重复执行会被允许,且没有提示。因为 Makefile 监控不到目标文件认为它没有生成。

2、Makefile的自动推导

在之前的 Makefile文件中,我们自己编写了生成.o文件的命令。但是 Makefile 也可以自动推导。

这里直接指定了依赖项的.o文件,它会自动推导生成。

另外 clean 命令下的- 表示忽略错误,因为这个命令的错误(如rm无法删除,不存在xxx文件)这对我们没有影响,所以忽略。

target := file_io_test dep := file_io_test.o $(target):$(dep) gcc $(dep) -o $(target) .PHONY:clean clean: -rm $(target) $(dep)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 9:17:12

5分钟掌握歌词滚动姬:免费开源的LRC歌词制作工具完全指南

5分钟掌握歌词滚动姬&#xff1a;免费开源的LRC歌词制作工具完全指南 【免费下载链接】lrc-maker 歌词滚动姬&#xff5c;可能是你所能见到的最好用的歌词制作工具 项目地址: https://gitcode.com/gh_mirrors/lr/lrc-maker 歌词滚动姬&#xff08;LRC Maker&#xff09;…

作者头像 李华
网站建设 2026/4/18 9:13:15

剪映自动化终极指南:用Python脚本批量处理视频的完整教程

剪映自动化终极指南&#xff1a;用Python脚本批量处理视频的完整教程 【免费下载链接】JianYingApi Third Party JianYing Api. 第三方剪映Api 项目地址: https://gitcode.com/gh_mirrors/ji/JianYingApi 还在为重复的视频剪辑工作烦恼吗&#xff1f;每天需要处理几十个…

作者头像 李华
网站建设 2026/4/18 9:13:14

飞书文档批量导出神器:3分钟搞定700+文档迁移,支持全平台运行

飞书文档批量导出神器&#xff1a;3分钟搞定700文档迁移&#xff0c;支持全平台运行 【免费下载链接】feishu-doc-export 飞书文档导出服务 项目地址: https://gitcode.com/gh_mirrors/fe/feishu-doc-export 还在为团队知识库迁移而头疼吗&#xff1f;面对飞书中堆积如山…

作者头像 李华
网站建设 2026/4/18 9:12:15

Linux命令:ip

ip 命令 基本介绍 ip 命令是 Linux 系统中用于网络配置的现代工具&#xff0c;是 ifconfig、route、arp 等命令的替代品。它提供了更强大、更灵活的网络配置功能&#xff0c;是 Linux 系统中常用的网络工具之一。 资料合集&#xff1a;https://pan.quark.cn/s/6fe3007c3e95、ht…

作者头像 李华
网站建设 2026/4/18 9:12:13

Thal深度解析:如何高效提取GitHub用户邮箱信息

Thal深度解析&#xff1a;如何高效提取GitHub用户邮箱信息 【免费下载链接】thal Getting started with Puppeteer and Chrome Headless for Web Scraping 项目地址: https://gitcode.com/gh_mirrors/th/thal Thal是一款基于Puppeteer和Chrome Headless技术构建的强大网…

作者头像 李华