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

Makefile自定义模式匹配:嵌套源文件对应扁平目标文件可行吗?

在Makefile中实现跨目录源文件到平级目标文件的模式匹配是否可行?

我通常会使用如下模式匹配规则来编译源文件:

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

按我的理解,这个规则会让每个目标(比如obj/file.o)关联对应的依赖项src/file.c。

现在我的场景是:src目录下有大量嵌套子目录,我已经通过递归命令收集了所有源文件,示例如下:

SOURCES := src/main.c src/dir1/a.c src/dir2/b.c

并通过模式替换生成了obj目录下无嵌套结构的目标文件列表:

OBJECTS := obj/main.o obj/a.o obj/b.o

我的需求是:无需手动编写所有目标与依赖项,通过类似的模式匹配规则实现以下对应关系:

obj/main.o   依赖于    src/main.c
obj/a.o      依赖于    src/dir1/a.c
...

请问此类模式匹配在Makefile中是否可行?


可行,你可以通过静态模式规则或者自定义依赖映射来实现需求,以下是两种实用方案:

方案一:静态模式规则

利用Makefile的静态模式规则,结合notdir和filter函数匹配目标与对应源文件:

首先确保SOURCES和OBJECTS的生成逻辑正确(注意变量赋值不要加方括号):

# 递归收集所有src目录下的.c文件
SOURCES := $(shell find src -name "*.c")
# 生成平级的obj目标文件列表
OBJECTS := $(patsubst %.c,obj/%.o,$(notdir $(SOURCES)))

然后编写静态模式规则:

$(OBJECTS): obj/%.o:
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $(filter %/$(notdir $@:.o=.c),$(SOURCES)) -o $@

其中filter %/$(notdir $@:.o=.c),$(SOURCES)会从SOURCES列表中筛选出与当前目标文件同名的源文件(自动匹配其所在的子目录)。

方案二:自动生成依赖规则

通过foreach循环遍历源文件,为每个平级目标文件自动生成依赖关系:

# 递归收集源文件
SOURCES := $(shell find src -name "*.c")
# 生成平级目标文件列表
OBJECTS := $(patsubst %.c,obj/%.o,$(notdir $(SOURCES)))

# 通用编译规则
$(OBJECTS): obj/%.o:
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

# 自动注入依赖关系
$(foreach src,$(SOURCES), \
    $(eval $(patsubst %.c,obj/%.o,$(notdir $(src))): $(src)) \
)

这个方法会逐个为每个目标文件绑定对应的源文件依赖,逻辑清晰,易于维护。

如果需要确保obj目录存在,可以添加伪目标:

.PHONY: all clean
all: $(OBJECTS)

obj:
    mkdir -p $@

$(OBJECTS): | obj

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:47:36