disquisitiones
disquisitiones

Reputation: 177

make does not rebuild target on header file modification

I have a makefile of this kind:

program: \
    a/a.o \
    b/b.o 
    $(CXX) $(CXXFLAGS) -o program \
        a/a.o \
        b/b.o

a.o: \
    a/a.cpp \
    a/a.h
    $(CXX) $(CXXFLAGS) -c a/a.cpp

b.o: \
    b/b.cpp \
    b/b.h
    $(CXX) $(CXXFLAGS) -c b/b.cpp

So in the directory of the makefile I have two subdirectories a and b that contain respectively a.h, a.cpp and b.h, b.cpp. The problem is that if I modify a .cpp file, issuing a make rebuilds the target program but if I modify an .h file make do not rebuilds anything but says

make: `program' is up to date.

I can't understand why, because the .h files are in the prerequisites line along with the .cpp files. Interestingly, if I issue a make on an object file target like

$ make a.o 

instead, the modifications to a/a.h are detected and the target a/a.o is rebuild. Where is the problem?

Upvotes: 1

Views: 396

Answers (1)

Reinier Torenbeek
Reinier Torenbeek

Reputation: 17383

The subdirectories that you added to the question later are causing the problem indeed. The target program depends on a/a.o and b/b.o, but there are no explicit rules to make those to .o files -- only the targets a.o and b.o are present but those are not in the subdirectories.

Therefore, make will look for implicit rules to build a/a.o and b/b.o. That rule does exist, you will see it being found when you run make -d. That implicit rule depends on a/file_a.cpp only, not on a/file_a.h. Therefore, changing a/file_a.cpp will make a/a.o out of date according to that implicit rule, whereas a/file_a.h will not.

For your reference, the make User's Manual has a section Catalogue of Implicit Rules. That also explains that you can use the argument --no-builtin-rules to avoid that implicit behavior. If you use that, you will see that make can not find any rules to make a/a.o and b/b.o.

Finally, running make a.o will run the recipe for the target a.o as defined in your makefile. That target does have a/a.h as its prerequisite so any change to that file will result in a recompile. But essentially, that has nothing to do with the target program, which has different prerequisites.

Upvotes: 2

Related Questions