如何使用Make编译子目录指定文件并输出至obj文件夹?
问题解决:Makefile编译子目录文件报错修复
错误原因
你的编译命令报错是因为使用-c参数时传入了多个源文件,同时指定了单个-o输出文件。gcc的-c参数要求每个源文件单独生成对应的目标文件,不能将多个源文件编译输出到同一个.o文件中。
问题出在你的编译规则:
$(BUILD_DIR)/%.o: %.cpp $(TEST_SRCS) @echo compiling $^ $(CC) $(CFLAGS) -c $^ -o $@
这里的$^会展开成当前.cpp文件加上$(TEST_SRCS)的所有文件,导致编译时同时传入main.cpp和under_test/test_code.cpp,触发gcc的错误。
修正后的Makefile配置
以下是符合需求的完整Makefile,支持编译子目录文件并将目标文件输出到./obj目录(保留子目录结构):
TARGET_EXEC ?= unit_test IDIR = ./include CC = g++ --std=c++14 CFLAGS = -g -I$(IDIR) -Iunder_test BUILD_DIR = obj # 当前目录所有.cpp文件 SRCS = $(wildcard *.cpp) # 子目录测试文件 TEST_SRCS = under_test/test_code.cpp # 合并所有需要编译的源文件 ALL_SRCS = $(SRCS) $(TEST_SRCS) # 生成对应的目标文件路径(保留子目录结构) OBJ = $(ALL_SRCS:%.cpp=$(BUILD_DIR)/%.o) LIBS = -lgtest -lgmock all: $(TARGET_EXEC) $(TARGET_EXEC): $(OBJ) @echo linking $^ $(CC) $(OBJ) -o $@ $(CFLAGS) $(LIBS) # 通用编译规则:自动创建目标文件所在子目录,单个源文件编译 $(BUILD_DIR)/%.o: %.cpp @mkdir -p $(dir $@) @echo compiling $< $(CC) $(CFLAGS) -c $< -o $@ .PHONY: clean show SOURCES := $(shell basename -a under_test/test_code.cpp \ under_test/more_test_code.cpp) show: echo $(SOURCES) clean: rm -rf $(BUILD_DIR) rm -f $(TARGET_EXEC) *~ core $(IDIR)/*~
关键修改点
- 合并源文件列表:将
SRCS和TEST_SRCS合并为ALL_SRCS,确保所有需要编译的文件都被纳入构建流程。 - 目标文件路径生成:通过
$(ALL_SRCS:%.cpp=$(BUILD_DIR)/%.o)保留源文件的子目录结构,比如under_test/test_code.cpp会生成obj/under_test/test_code.o。 - 修复编译规则:
- 使用
$<代替$^,只取当前单个源文件作为编译输入。 - 添加
mkdir -p $(dir $@)自动创建目标文件所需的子目录,避免目录不存在的错误。
- 使用
- 优化清理规则:使用
rm -rf $(BUILD_DIR)彻底删除整个obj目录,包括子目录和其中的目标文件。
内容的提问来源于stack exchange,提问作者alicevirgin
相关产品推荐
相关产品推荐

