Makefile核心教程(六) --- 一文吃透 Makefile 通配符

文章目录

在编写 Makefile 时,我们经常需要处理多个文件:比如编译所有 .c 文件,或者清理所有 .o 文件。如果逐个列举文件名,不仅繁琐而且难以维护。通配符正是为了解决这类问题而设计的。本文将彻底讲清楚这个概念,从用法到避坑指南,配合实例,让你一次性吃透。

一、通配符介绍

1. 什么是通配符?

通配符是一种用于匹配文件名的特殊字符,是 Makefile 提供的文件名模式匹配语法,用于批量匹配文件路径、文件名、后缀名,避免手动罗列大量文件。

Makefile 核心的四个通配符 *?[]%。这是你必须记住的全部,没有更多了。本文总结前三个通配符,% 在下一篇文章总结模式规则内容会详细讲解。

2. 为什么需要通配符

简化书写:批量代替大量文件名,代码极简洁。

自动适配:文件增删无需修改 Makefile 规则。

通用规则:一套规则适配所有同类文件(.c→.o)。

降低错误:避免手动写文件名的拼写错误。

二、通配符的用法

1. 通配符 * :匹配任意长度的任意字符

核心作用:匹配当前目录下非隐藏文件(不以.开头)的任意名称,支持指定后缀 / 前缀的匹配。

注意:不匹配隐藏文件(如.gitignore.test.c),若需匹配隐藏文件需显式指定.(如.*.c)。

例如:

  • *.c:匹配当前目录下所有后缀为.c的 C 语言源文件(如main.cutils.c)。
  • test*:匹配当前目录下所有以test开头的文件 / 目录(如test.ctest1.otest_dir)。
  • *_lib.*:匹配当前目录下所有以_lib结尾、且带有后缀的文件(如math_lib.clog_lib.o)。

2. 通配符 ?:匹配任意单个字符

核心作用:匹配文件名中某一个位置的任意单个字符,长度严格为 1。

例如:

  • test?.c:匹配test1.ctesta.ctest_.c,但不匹配test.c(无额外字符),也不匹配test12.c(两个字符)。
  • a?b.c:匹配a1b.caXb.c,但不匹配ab.ca12b.c

3. 通配符 []:匹配方括号内的任意单个字符

核心作用:匹配方括号内列举的任意单个字符。

扩展:GNU Make 支持[!...][^...](反向匹配),表示匹配除了方括号里列出的字符之外的任意单个字符,或者更直白一点:只要不是方括号中写的那些字符,都能匹配上。

例如:

  • test[123].c:枚举匹配,仅匹配test1.ctest2.ctest3.c
  • test[a-z].c:范围匹配,匹配testa.c~testz.c的所有小写字母结尾的文件。
  • test[0-9A-Z].c:范围组合,匹配数字(0-9)或大写字母(A-Z)结尾的文件。
  • test[!0-9].c:反向匹配,不匹配数字结尾的test0.c~test9.c文件(如匹配testa.c,不匹配test5.c)。

三、重要注意事项(避坑指南)

  1. 变量定义中使用*,必须配合wildcard函数

直接在变量中写*,Make 不会自动展开为文件列表,而是将其视为普通字符串;需使用$(wildcard 通配符)函数来触发文件匹配。

例如:

bash 复制代码
 # 错误用法:SRC的值是字符串"*.c",不是实际的.c文件列表
SRC_ERROR = *.c

# 正确用法:通过wildcard函数展开,SRC获取当前目录下所有.c文件
SRC = $(wildcard *.c)
  1. 通配符不匹配子目录

*.c 只匹配当前目录,不匹配子文件夹。要匹配子目录,可以用:*/*.c (匹配下一层子目录)或者指定目录dir/*.c

bash 复制代码
# 只匹配当前目录的.c文件
SRC = $(wildcard *.c) $(wildcard src/*.c)

# 匹配子目录下的.c文件(如src/目录)
SRC_SUB = $(wildcard src/*.c)
SRC_SUB = $(wildcard */*.c)

四、完整示例

完整源码请前往知识星球【源码】专栏下载,下载后详看目录中的readme.txt文件内容,有疑问欢迎星球内免费提问。

五、写在最后

欢迎加入嵌入式技术部落知识星球,该星球是高质量、干净、专业的嵌入式技术交流互助圈,编程教学,实战项目与源码解析,职场答疑,嵌入式咨询与学习指南,简历辅导等全方位支持。

加入方式,知识星球app搜索"嵌入式技术部落"。

相关推荐
Tisfy33 分钟前
LeetCode 2058.找出临界点之间的最小和最大距离:遍历+遇到极值则更新(这种题谁空间复杂度不是O(1)啊)
linux·数据库·leetcode·链表·题解·模拟·遍历
liulilittle38 分钟前
REALITY 代理隧道的有效检测方法: 被动、主动与确定性三层实证研究
linux·服务器·网络·网络协议·安全·网络安全·通信
邪修king1 小时前
Re:Linux 系统篇(十五):进程篇(四):进程切换深度解析 —— CPU 寄存器、进程上下文与切换全流程万字详解
linux·运维·服务器
高亦真2 小时前
今天是学习嵌入式的第33天
linux·学习·算法
cuijiecheng20182 小时前
Rocky Linux 安装 libltc、ltc-tools 和 ltcdump
linux
BlueAsia_Lab2 小时前
BQB 认证执行标准是什么?核心条款通俗解读
linux·运维·网络
小小、码农2 小时前
【网络】套接字(Socket)编程——TCP版
linux·服务器·网络·c++·网络协议·tcp/ip
邪修king2 小时前
Re:Linux 系统篇(十六):进程篇(五):O (1) 调度算法深度解析 —— 优先级数组、位图优化与活跃 / 过期双队列
linux·运维·算法
苏三福2 小时前
ubuntu 在文件管理系统中用sftp打开远程文件空白的问题解决
linux·运维·ubuntu
邪修king2 小时前
Re:Linux 系统篇(十四):进程篇(三):进程退出与特殊进程 —— 僵尸 Z 状态、孤儿进程深度解析
linux·运维·服务器