You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNU Make:如何结合子目录使用模式规则?

问题

我原本的Makefile构建规则如下:

SRCS := $(shell find . -name '*.c')
HEADERS := $(shell find . -name '*.h')
OBJS := $(SRCS:.c=.o)

%.o : %.c
  $(CC) -c $(CFLAGS) $< -o $@

executable : $(OBJS) $(HEADERS)
  $(CC) $(CFLAGS) $(OBJS) -o executable

我希望将.c和.h文件移至src/目录,同时将.o文件生成在obj/目录中,但遇到了困难:

SRCS := $(shell find src/ -name '*.c')
HEADERS := $(shell find src/ -name '*.h')
OBJS := $(SRCS:.c=.o)  <- 这一行我该替换成什么??

obj/ :
  mkdir -p obj

obj/%.o : src/%.c obj/
  $(CC) -c $(CFLAGS) $< -o $@

bin/ :
  mkdir -p bin

bin/executable : $(OBJS) $(HEADERS) bin/
  $(CC) $(CFLAGS) $(OBJS) -o bin/executable

有没有简便方法从src/%.c文件路径生成obj/%.o文件路径?我查阅了文档,但不知道该搜索哪些关键词。

解决方案

要实现src/下的.c到obj/下.o的路径转换,用Make的模式替换就能轻松搞定,有两种简洁写法:

写法1:使用patsubst函数

OBJS := $(patsubst src/%.c, obj/%.o, $(SRCS))

这个函数会把$(SRCS)中所有匹配src/%.c的字符串,替换成对应的obj/%.o,完全匹配你的需求。

写法2:简化的原生替换语法

如果偏好更简洁的写法,也可以直接用Make的原生替换规则:

OBJS := $(SRCS:src/%.c=obj/%.o)

效果和patsubst完全一致,是Make中专门针对模式匹配的简化写法。

修正后的完整Makefile

替换OBJS行后,还可以优化目录创建逻辑(不用单独写obj/、bin/规则),最终版本如下:

SRCS := $(shell find src/ -name '*.c')
HEADERS := $(shell find src/ -name '*.h')
OBJS := $(SRCS:src/%.c=obj/%.o)

# 编译.c为.o,自动创建obj目录
obj/%.o : src/%.c
  @mkdir -p $(dir $@)
  $(CC) -c $(CFLAGS) $< -o $@

# 链接生成最终可执行文件,自动创建bin目录
bin/executable : $(OBJS) $(HEADERS)
  @mkdir -p $(dir $@)
  $(CC) $(CFLAGS) $(OBJS) -o $@

# 可选:清理生成文件的规则
clean:
  rm -rf obj/ bin/

相关知识点提示

你需要搜索的关键词是 Makefile pattern substitution(模式替换)或者 Makefile path transformation(路径转换),这些关键词能快速定位到官方文档里的对应内容。
另外,$(dir $@)会自动提取目标文件的目录部分(比如obj/test.o对应的目录是obj/),配合mkdir -p可以自动创建所需目录,省去单独维护目录规则的麻烦。

内容的提问来源于stack exchange,提问作者kerkeslager

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 09:31:13