Makefile编译时同一.cpp生成多份.o导致多重定义错误的解决办法
问题根本原因
原来的.o生成规则写法存在逻辑错误:
$(CPP_OBJ): $(CPP_SRC) $(VERBOSE)$(MKDIR) -p '$(@D)' @$(ECHO) 'Compiling $<' $(VERBOSE)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INC) -c $< -o $@
- 这个规则的含义是:每一个生成
.o的目标,都依赖所有列在$(CPP_SRC)里的源文件 - Make的自动变量
$<只会取依赖列表里的第一个文件,也就是你定义的第一个源文件Reactor.cpp - 所以不管是生成
Reactor.o还是TestReactor.o,实际编译的都是Reactor.cpp,最终两个.o文件包含完全相同的符号,链接时自然报多重定义错误。
你后续修改的方案是可行的,通过路径反查对应源文件的逻辑解决了匹配问题,但还有更符合Make原生设计、更简洁的实现方案。
更优实现方案
直接使用Make的模式规则来匹配源文件和目标文件的对应关系,不需要手动做路径字符串替换:
# 模式规则:build_dir下的任意.o文件,对应项目根目录下同名的.cpp文件 $(BLD_DIR)/%.o: $(PRJ_DIR)/%.cpp $(VERBOSE)$(MKDIR) -p '$(@D)' @$(ECHO) 'Compiling $<' $(VERBOSE)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INC) -c $< -o $@
这个方案的优势:
- 完全利用Make原生的模式匹配能力,不需要额外写
eval做路径转换,可读性和可维护性更高 - 自动完成源文件和目标文件的一一对应,新增源文件不需要修改编译规则
- 你原来配置的
-MMD -MP生成头文件依赖、-include $(DEP)引入依赖的逻辑可以完全复用,不需要调整。
内容的提问来源于stack exchange,提问作者Kyle Gagnon
相关产品推荐
相关产品推荐

