minomic
minomic

Reputation: 665

Makefile - rebuild with modified header files

In my project I have some header files which contain methods (e.g. for template classes). All these header files are included in a single file header.h, which is then included in every cpp file. This way, I have to change the code just in one place. There are also some .h files without a corresponding .cpp file.
Then I have this makefile:

# Makefile

.PHONY: run clean rebuild

CC     = g++
CFLAGS = -Wall -Ofast -std=c++0x -pthread
RM     = rm -f
EXEC   = main

SRC    = $(wildcard *.cpp)
OBJ    = $(SRC:.cpp=.o)

$(EXEC): $(OBJ)
    $(CC) $(CFLAGS) -o $@ $(OBJ)

%.o: %.cpp
    $(CC) $(CFLAGS) -c $^

run: $(EXEC)
    ./$(EXEC)

clean:
    $(RM) $(EXEC) *.o *.gch *~

rebuild: clean $(EXEC)

Everything works fine, except for one small but annoying detail: if I modify a cpp file, then I can do make and everything is updated correctly, but if I modify a header file then I have to remove everything and recompile from scratch (and this is the reason why I have that ugly rebuild target), otherwise the edit will have no effect.

Is there a way to make things better without restructuring the entire code?

EDIT

I tried with this makefile

.PHONY: run clean rebuild

CC     = g++
CFLAGS = -Wall -Ofast -std=c++0x -pthread
RM     = rm -f
EXEC   = main

SRC    = $(wildcard *.cpp)
OBJ    = $(SRC:.cpp=.o)

$(EXEC): $(OBJ)
    $(CC) $(CFLAGS) -o $@ $(OBJ)

%.o: %.cpp headers.h
    $(CC) $(CFLAGS) -c $<

run: $(EXEC)
    ./$(EXEC)

clean:
    $(RM) $(EXEC) *.o *.gch *.d *~

rebuild: clean $(EXEC)

but the result is not what I want: if I modify a single header file and the do make, it tells me that the target is up to date, while I would like it to be recompiled.

Upvotes: 2

Views: 3085

Answers (2)

Beta
Beta

Reputation: 99084

Suppose you have foo.cpp, which contains the line:

#include "bar.h"

Your generic rule:

%.o: %.cpp
    $(CC) $(CFLAGS) -c $^

will not rebuild foo.o when bar.h has been modified (and foo.o is called for). It would work if you had an additional rule for foo.o:

%.o: %.cpp
    $(CC) $(CFLAGS) -c $<  # note the change of automatic variable

foo.o: bar.h

Writing such rules by hand would be a pain, but g++ will do it for you:

%.o: %.cpp
    $(CC) $(CFLAGS) -c -MMD $<

This command will produce the file foo.d (as a side effect of building foo.o) which contains the line:

foo.o: bar.h

What good does it do you, having that line in a separate file? You can pull it into the makefile with a line (at the end of the makefile) like this:

-include *.d

(If this approach seems amazingly simple, that's because a lot of smart people put a lot of thought into it.)

Upvotes: 11

urban
urban

Reputation: 5682

Not a Makefile expert, have a look at this. There are multiple solutions using -MM, -MD and -MF gcc flag. The highest voted answer suggests the following:

depend: .depend

.depend: $(SRCS)
        rm -f ./.depend
        $(CC) $(CFLAGS) -MM $^ -MF  ./.depend;

include .depend

As far as I understand that should generate the correct dependencies for you and it seems to be the correct way to go. However, I have never used it, I would have tried adding the header files in the dependencies (appending a new target for %.o):

%.o: %.cpp %.h header.h
    $(CC) $(CFLAGS) -c $<

Note that I have changed $^ to $< in order to get the first dependency only (which is the cpp) and I appended the header.h to force recompile when this changes. The last might not be required, depending on what you do in there, and it will result in inefficient compiles since changing it will recompile all of your .o files

Upvotes: 1

Related Questions