使用Make编译多路径代码时出现"No rule to make target"错误求助
问题描述
尝试使用Make编译程序,编写的Makefile代码如下:
INC_DIR = ./include BIN_DIR = ./bin SRC_DIR = ./src1 ./src2 ./src3 OBJ_DIR = ./obj SRC = $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c)) OBJ = $(patsubst %.c,${OBJ_DIR}/%.o,$(notdir ${SRC})) TARGET1 = main BIN_TARGET1 = ${BIN_DIR}/${TARGET1} CC = gcc CFLAGS = -g -Wall -I${INC_DIR} CFLAGS += -DLOG_USE_COLOR ${BIN_TARGET1}:${OBJ} $(CC) $(OBJ) -o $@ ${OBJ_DIR}/%.o:$(foreach dir,$(SRC_DIR),$(dir)/%.c) $(CC) $(CFLAGS) -c $< -o $@ .PHONY:clean clean: rm -rf ${BIN_TARGET1} rm -rf ${OBJ_DIR}/*.o @echo ${SRC}
执行Make后得到报错:
make: *** No rule to make target 'obj/main.o', needed by 'bin/main'. Stop.
问题原因与修复方案
核心问题
你的模式规则 ${OBJ_DIR}/%.o:$(foreach dir,$(SRC_DIR),$(dir)/%.c) 存在逻辑错误:当Make尝试匹配obj/main.o时,会把模式展开为src1/main.c src2/main.c src3/main.c,这意味着Make会认为所有这三个文件都必须存在才能生成obj/main.o,但实际上你只需要其中一个存在的源文件来编译对应的目标文件。
修复方法
方案1:使用VPATH指定源文件搜索路径
修改Makefile,添加VPATH变量告诉Make去哪里找源文件,同时简化模式规则:
INC_DIR = ./include BIN_DIR = ./bin SRC_DIR = ./src1 ./src2 ./src3 OBJ_DIR = ./obj # 指定源文件搜索路径 VPATH = $(SRC_DIR) SRC = $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c)) OBJ = $(patsubst %.c,${OBJ_DIR}/%.o,$(notdir ${SRC})) TARGET1 = main BIN_TARGET1 = ${BIN_DIR}/${TARGET1} CC = gcc CFLAGS = -g -Wall -I${INC_DIR} CFLAGS += -DLOG_USE_COLOR ${BIN_TARGET1}:${OBJ} $(CC) $(OBJ) -o $@ # 简化模式规则,VPATH会自动搜索SRC_DIR下的源文件 ${OBJ_DIR}/%.o:%.c $(CC) $(CFLAGS) -c $< -o $@ .PHONY:clean clean: rm -rf ${BIN_TARGET1} rm -rf ${OBJ_DIR}/*.o @echo ${SRC}
方案2:使用静态模式规则匹配对应源文件
如果不想用VPATH,可以通过静态模式规则明确关联每个目标文件和对应的源文件:
INC_DIR = ./include BIN_DIR = ./bin SRC_DIR = ./src1 ./src2 ./src3 OBJ_DIR = ./obj SRC = $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c)) # 保留源文件的完整路径,方便后续匹配 OBJ = $(patsubst %.c,${OBJ_DIR}/%.o,$(notdir ${SRC})) # 建立源文件和目标文件的映射 SRC_OBJ_MAP = $(foreach src,$(SRC),$(OBJ_DIR)/$(notdir $(src:.c=.o)):$(src)) TARGET1 = main BIN_TARGET1 = ${BIN_DIR}/${TARGET1} CC = gcc CFLAGS = -g -Wall -I${INC_DIR} CFLAGS += -DLOG_USE_COLOR ${BIN_TARGET1}:${OBJ} $(CC) $(OBJ) -o $@ # 使用静态模式规则,逐个匹配源文件和目标文件 $(SRC_OBJ_MAP) $(CC) $(CFLAGS) -c $< -o $@ .PHONY:clean clean: rm -rf ${BIN_TARGET1} rm -rf ${OBJ_DIR}/*.o @echo ${SRC}
额外注意事项
- 确保
obj和bin目录已经存在,如果不想手动创建,可以在Makefile中添加创建目录的规则:
然后在目标规则中依赖这些目录:${OBJ_DIR} ${BIN_DIR}: mkdir -p $@${BIN_TARGET1}:${OBJ_DIR} ${BIN_DIR} ${OBJ} $(CC) $(OBJ) -o $@
内容的提问来源于stack exchange,提问作者BowinChow
相关产品推荐
相关产品推荐

