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

如何用Makefile编译子目录文件?解决file2.o不存在编译报错

问题分析

你的核心问题出在Makefile的模式规则%.o : %.c上——这个规则只匹配“与.o文件同目录”的.c文件。而file2.o的依赖是dir/file2.c,源文件在子目录里,和目标.o的路径不匹配,所以Make不会执行你自定义的编译规则,反而会尝试用内置默认规则(但默认规则不知道要去子目录找源文件),最终导致file2.o根本没被生成,链接阶段自然报错找不到它。

解决方案

下面提供几种从简单到通用的优化方案,替代逐个写编译命令的繁琐方式:

方案1:静态模式规则(适配单一子目录场景)

如果只有dir这一个子目录,用静态模式规则明确指定子目录源文件对应的.o目标:

CFLAGS = -ansi -Wall -pedantic -g -I$(LIBRE_INC) -Iinclude -std=gnu99
LDFLAGS = -lm
EXEC = out
CC = gcc

out : file1.o file2.o
	${CC} -o $@ $^ $(CFLAGS) $(LDFLAGS)

# 处理当前目录的源文件
file1.o: file1.c file1.h
	${CC} -c $< $(CFLAGS)

# 用静态模式规则处理子目录的file2.o
file2.o: %.o : dir/%.c dir/%.h
	${CC} -c $< $(CFLAGS) -o $@

这个规则会明确把dir/file2.c编译成当前目录的file2.o,完全符合你的需求。

方案2:通用模式规则(支持任意单层子目录)

如果后续可能添加更多单层子目录的源文件,可以用更通用的模式规则匹配所有子目录的.c文件:

CFLAGS = -ansi -Wall -pedantic -g -I$(LIBRE_INC) -Iinclude -std=gnu99
LDFLAGS = -lm
EXEC = out
CC = gcc

out : file1.o file2.o
	${CC} -o $@ $^ $(CFLAGS) $(LDFLAGS)

file1.o: file1.c file1.h

# 匹配任意子目录下的.c文件,生成当前目录的.o
%.o : */%.c */%.h
	${CC} -c $< $(CFLAGS) -o $@

*/%.c会匹配所有一级子目录下的同名.c文件,比如dir/file2.c会匹配file2.o的模式。

方案3:变量驱动的通用写法(推荐,适配多文件/多目录)

如果项目规模会扩大,推荐用变量管理所有源文件,自动推导目标文件和依赖,避免硬编码:

CFLAGS = -ansi -Wall -pedantic -g -I$(LIBRE_INC) -Iinclude -std=gnu99
LDFLAGS = -lm
EXEC = out
CC = gcc

# 定义所有源文件(包括子目录的)
SRCS = file1.c dir/file2.c
# 把所有.c文件转换为当前目录的.o文件
OBJS = $(patsubst %.c, %.o, $(notdir $(SRCS)))

out : $(OBJS)
	$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)

# 静态模式规则:为每个.o找到对应的源文件路径
$(OBJS): %.o :
	$(CC) -c $(filter %/$*.c, $(SRCS)) $(CFLAGS) -o $@

# 自动生成头文件依赖(避免修改头文件后忘记重新编译)
-include $(OBJS:.o=.d)

%.d: %.c
	$(CC) -MM $(CFLAGS) $< > $@.tmp
	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.tmp > $@
	rm -f $@.tmp

这种写法的优势是:

  • 新增源文件时只需要更新SRCS变量
  • 自动处理头文件依赖,修改.h文件会自动触发重新编译
  • 完全避免重复编写编译命令
为什么原规则不生效?

再回顾下你的原规则:

%.o : %.c
	${CC} -c $< $(CFLAGS) $(LDFLAGS)

Make的模式规则要求目标和依赖的路径结构完全匹配——比如file2.o对应的依赖必须是file2.c(同一目录),而你的依赖是dir/file2.c,路径不匹配,所以这个规则不会被触发。Make会尝试用内置的默认编译规则,但默认规则不知道要去dir目录找file2.c,所以根本不会生成file2.o,链接时就出现了找不到文件的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:19:46