关于makefile中通配符*和%的介绍

在 Makefile 中,* 和 % 都是用于匹配文件名的通配符,但它们的作用场景匹配规则有显著区别,理解两者的差异是编写高效 Makefile 的关键。

1. *:文件名通配符(用于匹配现有文件)

* 是shell 风格的通配符,用于匹配当前目录中已存在的文件名,主要在以下场景使用:

(1)匹配文件列表
  • * 匹配任意长度的字符(除了路径分隔符 /)。
  • 常用于获取符合条件的文件列表(如所有 .c 源文件、所有 .o 目标文件)。

示例

# 匹配当前目录所有 .c 源文件
SRCS = *.c

# 匹配当前目录所有 .o 目标文件
OBJS = *.o

# 编译所有 .c 文件为 .o 文件
all: $(OBJS)
    gcc $(OBJS) -o main

# 生成单个 .o 文件的规则
%.o: %.c
    gcc -c $< -o $@
  • 这里 *.c 会被展开为当前目录中所有 .c 结尾的文件(如 a.cb.c)。
  • 注意:* 仅匹配已经存在的文件,如果文件不存在,会被当作普通字符串处理。
(2)在 wildcard 函数中使用

当需要在变量中动态获取文件列表时,通常结合 wildcard 函数使用(避免 * 被当作字符串字面量):

# 正确获取所有 .c 文件(即使变量定义时文件不存在,后续创建后也能匹配)
SRCS = $(wildcard *.c)

# 匹配子目录中的文件(如 src 目录下的 .c 文件)
SRCS += $(wildcard src/*.c)
  • wildcard *.c 会返回当前目录中所有 .c 文件的列表,比直接写 *.c 更可靠。

2. %:模式匹配符(用于规则中的模式规则)

% 是 Makefile 特有的模式匹配符,主要用于模式规则(Pattern Rules) 中,定义 “一类文件” 的通用构建规则,不依赖文件是否存在。

(1)基本用法:匹配文件名的对应部分

在模式规则中,% 代表文件名中 “任意长度的字符串”,且在目标和依赖中必须匹配相同的部分

经典示例:编译所有 .c 文件为 .o 文件的通用规则

# 模式规则:所有 .o 文件都由同名的 .c 文件编译生成
%.o: %.c
    gcc -c $< -o $@
  • 这里 % 是 “通配符占位符”:
    • 若目标是 a.o,则依赖会被自动识别为 a.c
    • 若目标是 b.o,则依赖会被自动识别为 b.c
  • 该规则适用于所有符合 “.o 对应 .c 的文件,无需为每个文件单独写规则。
(2)在变量和函数中使用 %

% 还可在 patsubst(模式替换)等函数中用于字符串替换:

# 获取所有 .c 文件列表
SRCS = $(wildcard *.c)  # 假设结果为 a.c b.c

# 将 .c 文件名替换为 .o(如 a.c → a.o,b.c → b.o)
OBJS = $(patsubst %.c, %.o, $(SRCS))  # 结果为 a.o b.o
  • patsubst %.c, %.o, $(SRCS) 表示:将 SRCS 中所有以 .c 结尾的字符串,替换为 .o 结尾。
(3)匹配路径中的文件

% 可以匹配包含路径的文件名,而 * 通常不跨路径匹配:

makefile

# 模式规则:编译 src 目录下的 .c 文件为 obj 目录下的 .o 文件
obj/%.o: src/%.c
    mkdir -p obj  # 确保 obj 目录存在
    gcc -c $< -o $@
  • 若目标是 obj/a.o,则依赖会被识别为 src/a.c% 匹配了 a 这部分。

3. * 和 % 的核心区别

特性*(通配符)%(模式匹配符)
作用场景匹配现有文件的名称(如获取文件列表)定义模式规则,匹配 “一类文件” 的通用规则
依赖文件存在性仅匹配已存在的文件不依赖文件是否存在,用于定义规则模板
匹配范围通常不跨路径(除非结合 **,部分版本支持)可匹配路径中的文件名(如 src/%.c
典型用法*.c$(wildcard *.o)%.o: %.c$(patsubst %.c, %.o, ...)

4. 常见错误与注意事项

  • 混淆 * 和 % 的使用场景

    • 错误:在模式规则中用 * 代替 %,如 *.o: *.c(这会被解析为 “所有 .o 文件依赖所有 .c 文件”,不符合预期)。
    • 正确:用 %.o: %.c 定义每个 .o 对应单个 .c 的规则。
  • * 在变量中的延迟展开

    • 直接写 SRCS = *.c 时,* 会在变量定义时展开(仅匹配当时存在的文件)。
    • 若后续新增 .c 文件,需要重新运行 make 才会识别,而 $(wildcard *.c) 会动态获取最新文件列表。
  • % 必须在目标和依赖中同时出现

    • 模式规则中,% 必须在目标和依赖中都存在(如 %.o: %.c),否则会被视为无效规则。

总结

  • * 是文件通配符,用于匹配当前目录中已存在的文件,适合获取文件列表。
  • % 是模式匹配符,用于定义通用规则(如所有 .o 依赖 .c),不依赖文件是否存在,是 Makefile 实现 “批量处理” 的核心机制。

灵活运用两者可以大幅简化 Makefile 的编写,尤其是 % 模式规则,能显著减少重复代码,提高可维护性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值