Andrew Falanga
Andrew Falanga

Reputation: 2484

Why isn't make detecting changes in header dependencies

I'm not sure what I'm doing wrong here. I'm trying to get make to figure out what dependencies my project has for, not only source files, but non-system included header files. I've many resources from this very site related to this subject.

Such as: Makefile header dependencies and Makefile, header dependencies

However, when I do

touch MyHeader.h

as a test to see if this works, my make process fails to rebuild the source files that include this header. So, here's what I have in my makefile (of relevance that is)

CPP=g++
CPPFLAGS=-Iadditional/includes -MMD
CXXFLAGS=-std=c++0x -c 
# not every source file in this directory needs to be included in this build
# this is because of shared code with Windows
SOURCESFILTER = File1.cpp File2.cpp

OBJ_DIR=obj
SOURCES = $(filter-out $(SOURCEFILTER),$(wildcard *.cpp))
OBJECTS = $(addprefix $(OBJ_DIR)/,$(SOURCES:.cpp=.o))

DEPENDENCIES = $(OBJECTS:.o=.d)

.PHONY: archive

archive : $(OBJECTS)
    ar mylib.a obj/*.o

-include $(DEPENDENCIES)

$(OBJ_DIR)/%.o: $(SOURCES) $(DEPENDENCIES)
    $(CPP) $(CPPFLAGS) $(CXXFLAGS) $< -o $@

I've verified that the above process does indeed generate the expected *.d files. I assume that I'm including them correctly. However, as mentioned, as a test I do: touch MyHeader.h

which is in the same directory as the sources, and rerun the make, none of the source files which include this header are remade. What am I missing?

Andy

Upvotes: 2

Views: 6449

Answers (1)

MadScientist
MadScientist

Reputation: 100781

First, you cannot include prerequisites in a suffix rule. Even if you could, you certainly would not want to include $(SOURCES) or $(DEPENDENCIES), because that would cause every object to rebuild whenever any source or dependency file changed.

Second, you cannot create the target file in a different directory from where make expects it to be. Make will put the place where it wants to find the target in the variable $@, and you must write the output into that location exactly. If you ever see a rule that modifies the target, such as above where you use obj/$@, that won't work.

Most likely GCC is writing the files as obj/foo.d, but your include is trying to include foo.d but that doesn't exist... but since you used -include make doesn't complain.

I recommend you first write the object files into the local directory and get that working with dependencies. Once that works, then read up on how to write targets to a different directory and/or ask again.

ETA:

Try something like this:

CXX := g++
CPPFLAGS := -Iadditional/includes -MMD
CXXFLAGS := -std=c++0x
# not every source file in this directory needs to be included in this build
# this is because of shared code with Windows
SOURCESFILTER := File1.cpp File2.cpp

OBJ_DIR := obj
SOURCES := $(filter-out $(SOURCEFILTER),$(wildcard *.cpp))
OBJECTS := $(addprefix $(OBJ_DIR)/,$(SOURCES:.cpp=.o))

DEPENDENCIES := $(OBJECTS:.o=.d)

.PHONY: archive

archive: mylib.a

mylib.a: $(OBJECTS)
        $(AR) $@ $^

-include $(DEPENDENCIES)

$(OBJ_DIR)/%.o: %.cpp
        $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<

Upvotes: 4

Related Questions