首页 > 解决方案 > Make 不会重新编译头文件更改。尽管包括 .d 依赖文件

问题描述

在我的一个业余项目中,我对 Makefile 有一个非常奇怪的问题。

我有一个 Makefile(如下所示),它在https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html之后的 .d 文件中生成依赖信息。

问题是我的一个头文件(shader.h)的更改不会触发重新编译shader.o(在shader.cpp之外)。

当我重新组织项目中的目录结构时,最近开始出现问题,所以我怀疑它与此有关。

奇怪的是,如果我这样做make --print-data-base,它似乎确实找到了与 shader.d 文件匹配的正确先决条件。

目录结构如下:

|-src
  |-engine
    |-shader.h
    |-shader.cpp
|-bin
  |-Debug
    |-OpenGLTest
|-obj
  |-Debug
    |-engine
      |-shader.o
|-dep
  |-engine
    |-shader.d

生成文件:

WORKDIR = `pwd`

CC = gcc
CXX = g++
AR = ar
LD = g++
WINDRES = windres

INC = -I/usr/local/include
CFLAGS = -Wall -Werror
CXX_FLAGS = -std=c++11
RESINC =
LIBDIR = -L/usr/local/lib
LIB = -lSDL2 -lGLEW -framework OpenGL
LDFLAGS =

DEPDIR = dep
SRCDIR = src

INC_DEBUG = $(INC)
CFLAGS_DEBUG = $(CFLAGS) -g
RESINC_DEBUG = $(RESINC)
RCFLAGS_DEBUG = $(RCFLAGS)
LIBDIR_DEBUG = $(LIBDIR)
LIB_DEBUG = $(LIB)
LDFLAGS_DEBUG = $(LDFLAGS)
OBJDIR_DEBUG = obj/Debug
DEP_DEBUG =
OUT_DEBUG = bin/Debug/OpenGLTest

CXX_SRCS = $(wildcard $(SRCDIR)/*.cpp) $(wildcard $(SRCDIR)/**/*.cpp)
CXX_REL_SRCS = $(subst $(SRCDIR)/,,$(CXX_SRCS))
OBJS = $(CXX_REL_SRCS:%.cpp=%.o)

OBJ_DEBUG = $(addprefix $(OBJDIR_DEBUG)/,$(OBJS))

# ----------------------------- debug -----------------------------

clean: clean_debug clean_release
    rm -rf $(DEPDIR)

before_debug:
    @test -d bin/Debug || mkdir -p bin/Debug
    @test -d $(OBJDIR_DEBUG) || mkdir -p $(OBJDIR_DEBUG)
    @mkdir -p $(dir $(OBJ_DEBUG))

after_debug:

debug: before_debug out_debug after_debug

out_debug: before_debug $(OBJ_DEBUG) $(DEP_DEBUG)
    $(LD) $(LIBDIR_DEBUG) -o $(OUT_DEBUG) $(OBJ_DEBUG)  $(LDFLAGS_DEBUG) $(LIB_DEBUG)

$(OBJDIR_DEBUG)/%.o: $(SRCDIR)/%.cpp
    $(CXX) $(CFLAGS_DEBUG) $(CXX_FLAGS) $(INC_DEBUG) -c $< -o $@

clean_debug:
    rm -f $(OBJ_DEBUG) $(OUT_DEBUG)
    rm -rf bin/Debug
    rm -rf $(OBJDIR_DEBUG)

# ----------------------------- dependencies -----------------------------

# Generate dependencies in *.d files
$(DEPDIR)/%.d: $(SRCDIR)/%.cpp
    @test -d $(DEPDIR) || mkdir -p $(DEPDIR)
    @mkdir -p $(dir $@)
    @set -e; rm -f $@; \
         $(CXX) -MM $(CFLAGS) $(CXX_FLAGS) $(INC) $< > $@.$$$$; \
         sed 's,\(.*\)\.o[ :]*,$(OBJDIR_RELEASE)/\1.o $(OBJDIR_DEBUG)/\1.o $@ : ,g' < $@.$$$$ > $@; \
         rm -f $@.$$$$

# Include the *.d files
include $(patsubst %,$(DEPDIR)/%.d,$(basename $(CXX_REL_SRCS)))

# ----------------------------- targets -----------------------------

.PHONY: before_debug after_debug clean_debug

all: debug

着色器.d:

obj/Debug/shader.o dep/engine/shader.d : src/engine/shader.cpp src/engine/shader.h \
src/engine/transform.h src/engine/camera.h src/engine/constants.h

标签: c++makefile

解决方案


我会回答这个问题,因为@GM 在评论中发现了这个问题。

事实证明,依赖生成是有缺陷的。

在 shader.d 中obj/Debug/shader.o应该真的是obj/Debug/engine/shader.o. 如下所示修改 sed 命令可解决此问题。

sed 's,\(.*\)\.o[ :]*,$(OBJDIR_RELEASE)/$(subst $(SRCDIR)/,,$(dir $<))\1.o $(OBJDIR_DEBUG)/$(subst $(SRCDIR)/,,$(dir $<))\1.o $@ : ,g' < $@.$$$$ > $@;

推荐阅读