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

如何编写支持两级目录依赖的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:01:12