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
相关产品推荐
相关产品推荐

