Makefile依赖更新异常:编译正常但未重编依赖致可执行文件无更新
解决Makefile依赖更新失效问题
我来帮你排查这个问题,你的Makefile能正常编译源码,但无法追踪头文件变化重新编译,核心问题出在依赖文件的路径不匹配,还有几处细节需要调整,下面逐一分析:
问题根源分析
依赖文件路径错误
你用-MMD -MP编译时,会生成和目标.o文件同目录的.d依赖文件(比如objs/src/main.o对应objs/src/main.d),但你的DEP变量定义是:DEP = $(SRCS:.cc=.d)这会把
./src/main.cc转换成./src/main.d,而实际生成的.d文件在objs/目录下,导致-include $(DEP)根本没加载到正确的依赖信息,Make自然不知道头文件变化了。冗余的头文件依赖
你的.o文件规则里手动指定了./%.hh依赖:$(OBJDIR)/%.o : ./%.cc ./%.hh这不仅会强制要求每个
.cc必须对应一个.hh文件(否则会报错),还会覆盖-MMD自动生成的全量头文件依赖(比如某个.cc引用了其他目录的头文件,Make就追踪不到了)。CFLAGS参数的引号问题
$(addprefix "-I", $(shell find -type d))里的引号会被传递给g++,导致目录参数识别错误,比如"-Isrc"会被当成一个整体参数,g++无法正确解析这个包含目录。
修正后的Makefile
EXEC ?= program SRCS = $(shell find -name *.cc) OBJDIR = objs OBJS = $(SRCS:./%.cc=$(OBJDIR)/%.o) # 修正DEP路径:从OBJS转换,指向OBJDIR下的.d文件 DEP = $(OBJS:.o=.d) CXX = g++ # 去掉多余的引号,让-include目录参数正常解析 CFLAGS = -std=c++14 $(addprefix -I, $(shell find -type d)) ## Clean rule .PHONY: clean clean: rm -rf $(OBJDIR) rm -f $(EXEC) $(EXEC) : $(OBJS) @echo "Linking: $@" $(CXX) $(OBJS) -o $@ # 加载正确路径的依赖文件 -include $(DEP) # 去掉手动指定的./%.hh依赖,让-MMD自动追踪所有头文件 $(OBJDIR)/%.o : ./%.cc @mkdir -p $(@D) @echo "Compiling: $<" @$(CXX) -c $(CFLAGS) -MT $@ -MMD -MP -o $@ $<
验证方法
- 先执行
make clean清理旧文件 - 正常编译项目:
make - 修改任意一个头文件(比如某个
.hh或者被引用的其他头文件) - 再次执行
make,此时Make应该会自动重新编译依赖该头文件的.cc文件,并更新最终的可执行文件
内容的提问来源于stack exchange,提问作者Valentin Montmirail
相关产品推荐
相关产品推荐

