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

如何编写Makefile编译不同子目录下的多个源文件?

批量编译多目录源文件的Makefile实现方案

核心思路

不用手动逐个指定源文件,通过Makefile内置函数自动抓取子目录下的所有源文件,配合通用规则完成批量编译,核心用到以下几个特性:

  • wildcard:自动匹配指定目录下的目标文件
  • 路径替换:将源文件路径转换为对应的目标文件路径
  • vpath:指定源文件的搜索路径(可选,根据目标文件存放位置决定)

方案1:目标文件统一放到obj目录(推荐)

这种方式把编译生成的.o文件集中存放在根目录的obj文件夹下,保持源文件目录整洁。完整Makefile示例:

# 定义编译器和编译参数
CC := gcc
CFLAGS := -Wall -Wextra -g

# 自动抓取Mcal和Ecual目录下的所有.c文件
SRC_FILES := $(wildcard Mcal/*.c Ecual/*.c)
# 将源文件路径转换为obj目录下对应的.o文件路径(保留子目录结构)
OBJ_FILES := $(addprefix obj/, $(SRC_FILES:.c=.o))
# 最终生成的可执行文件名称
TARGET := my_project

# 指定make搜索.c文件的目录
vpath %.c Mcal Ecual

# 默认执行目标:生成可执行文件
all: $(TARGET)

# 链接所有.o文件生成可执行文件
$(TARGET): $(OBJ_FILES)
	$(CC) $(CFLAGS) $^ -o $@

# 通用编译规则:编译.c文件为对应路径的.o文件
obj/%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# 确保obj的子目录存在(编译前自动创建)
obj/Mcal obj/Ecual:
	mkdir -p $@

# 清理中间文件和可执行文件
clean:
	rm -rf obj $(TARGET)

# 声明伪目标,避免与同名文件冲突
.PHONY: all clean

关键部分解释:

  • wildcard Mcal/*.c Ecual/*.c:自动扫描两个子目录下的所有.c文件,无需手动逐个添加。
  • addprefix obj/, $(SRC_FILES:.c=.o):把每个源文件(比如Mcal/uart.c)转换成obj/Mcal/uart.o,保留子目录结构方便管理。
  • vpath %.c Mcal Ecual:告诉make,当需要查找.c文件时,去这两个目录搜索,确保通用规则能匹配到子目录里的源文件。
  • obj/Mcal obj/Ecual::编译前自动创建所需的目标目录,避免因目录不存在导致编译失败。

方案2:目标文件与源文件同目录

如果不需要单独存放中间文件,可以直接在源文件所在目录生成.o文件,Makefile会更简洁:

CC := gcc
CFLAGS := -Wall -Wextra -g

# 抓取所有子目录下的.c文件
SRC_FILES := $(wildcard Mcal/*.c Ecual/*.c)
# 直接将.c替换为.o,目标文件与源文件同目录
OBJ_FILES := $(SRC_FILES:.c=.o)
TARGET := my_project

all: $(TARGET)

# 链接生成可执行文件
$(TARGET): $(OBJ_FILES)
	$(CC) $(CFLAGS) $^ -o $@

# 通用规则:匹配任意路径下的.o和对应的.c
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# 清理命令
clean:
	rm -rf $(OBJ_FILES) $(TARGET)

.PHONY: all clean

这种方案中,%.o: %.c规则可以直接匹配Mcal/xxx.o依赖Mcal/xxx.c,因为路径是完整的,make会自动识别对应关系,不需要额外指定搜索路径。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:15:34