如何编写支持两级目录依赖的Makefile模式规则?
解决Makefile两级目录C文件编译的模式规则问题
项目结构
project |- bin |- src | | main.c | |- test | | | test.c | Makefile
现有问题
当前编写的Makefile仅能处理src目录下的一级C文件(比如将main.c编译为bin/main.o),但无法匹配src/test/test.c生成bin/test.o的依赖关系,需要调整模式规则以支持两级目录的编译需求。
现有Makefile代码:
dir_bin = ./bin dir_src = ./src srcs := $(wildcard $(dir_src)/*.c $(dir_src)/*/*.c) objs := $(addprefix $(dir_bin)/, $(notdir $(srcs:%.c=%.o))) .PHONY: all all: $(objs) $(dir_bin)/%.o: $(dir_src)/%.c $(cc) -o $@ $<
解决方案
方法一:使用vpath指定源文件搜索路径(推荐)
通过vpath指令告知Make在哪些目录下查找源文件,模式规则可简化为通用匹配,无需关心具体目录层级:
dir_bin = ./bin dir_src = ./src # 递归查找src下所有C文件(也可保留原wildcard写法) srcs := $(shell find $(dir_src) -name "*.c") # 将所有C文件对应到bin目录下的同名.o文件 objs := $(addprefix $(dir_bin)/, $(notdir $(srcs:.c=.o))) # 指定C源文件的搜索路径,覆盖一级和二级目录 vpath %.c $(dir_src) $(dir_src)/test .PHONY: all all: $(objs) # 通用模式规则:匹配任意目录下的.c文件,生成bin目录下的同名.o $(dir_bin)/%.o: %.c $(CC) -c $< -o $@
说明:
vpath %.c <路径>定义了Make查找.c文件的优先级目录,当需要生成bin/test.o时,Make会自动在src/test目录下定位到test.c。- 后续如果新增更多子目录,只需在
vpath中添加对应路径即可,扩展性更强。
方法二:编写多模式规则匹配不同层级
若不想使用vpath,可针对一级和二级目录分别编写模式规则:
dir_bin = ./bin dir_src = ./src # 匹配一级和二级目录下的C文件 srcs := $(wildcard $(dir_src)/*.c $(dir_src)/*/*.c) # 将src下的路径转换为bin目录下的.o路径,同时去掉子目录层级(比如src/test/test.c → bin/test.o) objs := $(patsubst $(dir_src)/%.c, $(dir_bin)/%.o, $(srcs)) objs := $(patsubst $(dir_bin)/%/%.o, $(dir_bin)/%.o, $(objs)) .PHONY: all all: $(objs) # 匹配二级目录下的C文件(比如src/test/test.c → bin/test.o) $(dir_bin)/%.o: $(dir_src)/%/%.c $(CC) -c $< -o $@ # 匹配一级目录下的C文件(比如src/main.c → bin/main.o) $(dir_bin)/%.o: $(dir_src)/%.c $(CC) -c $< -o $@
说明:
- 第一个模式规则
$(dir_bin)/%.o: $(dir_src)/%/%.c会匹配二级目录的情况,两个%分别对应文件名(test)和子目录名(test)。 - 第二个规则保留原有的一级目录匹配逻辑,确保
main.c正常编译。
内容的提问来源于stack exchange,提问作者Glorbo Florbo
相关产品推荐
相关产品推荐

