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搜索"嵌入式技术部落"。

相关推荐
jiuri_12152 小时前
OpenHarmony 移植 OpenSSH/sshd
linux·sshd·ohos
慕诗客2 小时前
英伟达Jetson Agx Orin更换开机Logo
linux
yy_xzz2 小时前
【Linux开发】01多线程编程:线程的创建与运行
linux·运维·服务器
我爱学习好爱好爱2 小时前
Ansible include任务复用 tags ignore_errors
linux·运维·ansible
YMWM_2 小时前
【问题修复】ubuntu24.04打不开windows的D盘
linux
淼淼爱喝水2 小时前
Ansible Ad-Hoc 命令基础实战(Linux 系统)
linux·服务器·数据库
yy_xzz2 小时前
【Linux开发】04Linux 线程的销毁
linux
HenryLiuu2 小时前
Ubuntu 20.04, cuda 12.1版本安装flash attention 2教程
linux·ubuntu
Boop_wu10 小时前
[Java 算法] 字符串
linux·运维·服务器·数据结构·算法·leetcode