Makefile自动创建obj/bin目录失败,报错找不到目标文件求解
问题描述
编写Makefile编译项目时,希望自动创建obj和bin目录,尝试将目录作为目标失败后,出现以下错误:
make: *** No rule to make target 'obj/main.o', needed by 'bin/main.out'. Stop.
使用的Makefile内容如下:
bin = ./bin/ src = ./src/ obj = ./obj/ CXX = g++ CCFLAGS = -Wall -g -c CXXFLAGS = -O3 HDRS = $(src)ShallowWater.h OBJS = $(obj)main.o $(obj)TimeIntegrate.o $(obj)derivatives.o $(obj)SetInitialConditions.o $(obj)SetBoundaryConditions.o $(obj)SetParameters.o LIBS = -lblas -lboost_program_options -fopenmp $(bin)main.out: $(OBJS) @mkdir -p $(obj) $(CXX) -o $@ $^ $(LIBS) $(obj)%.o: $(src)%.cpp $(HDRS) @mkdir -p $(obj) $(CXX) $(CXXFLAGS) -o $@ -c $<
推测问题在于目录不存在时,make将obj/main.o视为文件名而非文件路径。
解决方案
问题核心是Make在匹配模式规则前,会先检查目标文件的路径是否存在。当obj/目录未创建时,Make找不到生成obj/main.o的有效规则,因此报错。
正确的做法是将目录创建作为独立前置步骤,确保编译前obj/和bin/目录已存在,以下是修正后的Makefile:
bin = ./bin src = ./src obj = ./obj # 定义需要创建的目录 DIRS = $(obj) $(bin) CXX = g++ CXXFLAGS = -O3 -Wall -g -c HDRS = $(src)/ShallowWater.h OBJS = $(obj)/main.o $(obj)/TimeIntegrate.o $(obj)/derivatives.o $(obj)/SetInitialConditions.o $(obj)/SetBoundaryConditions.o $(obj)/SetParameters.o LIBS = -lblas -lboost_program_options -fopenmp # 目录创建规则 $(DIRS): @mkdir -p $@ # 可执行文件依赖目录和目标文件 $(bin)/main.out: $(DIRS) $(OBJS) $(CXX) -o $@ $^ $(LIBS) # 目标文件依赖源文件、头文件和对应目录 $(obj)/%.o: $(src)/%.cpp $(HDRS) $(obj) $(CXX) $(CXXFLAGS) -o $@ $<
关键修改说明
- 移除变量末尾的斜杠,后续用
/拼接路径更规范,避免重复斜杠问题 - 新增目录目标
DIRS,明确创建目录的规则 - 将目录作为可执行文件和目标文件的前置依赖,确保编译前目录已生成
- 合并编译参数:将原
CCFLAGS的参数整合到CXXFLAGS中,避免参数闲置
优化方案(使用Order-Only依赖)
如果不想因目录时间戳更新触发全量编译,可以用Order-Only依赖(|分隔),仅在目录不存在时执行创建操作:
$(obj)/%.o: $(src)/%.cpp $(HDRS) | $(obj) $(CXX) $(CXXFLAGS) -o $@ $< $(bin)/main.out: $(OBJS) | $(bin) $(CXX) -o $@ $^ $(LIBS)
内容的提问来源于stack exchange,提问作者user19665574
相关产品推荐
相关产品推荐

