Makefile - recompile

Viewed 25

My makefile always recompiles everything in directory if one header is changed. It's not a problem now but since I'm adding more to my program this is becoming and issue. I don't want to wait for a whole recompile if I add a new variable to a header of a separate class object. Here is my makefile:

CXX = g++
CPPFLAGS = -I -lm -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system

OBJ = CR_Main.o CarRental.o CR_Button.o CR_LoginMenu.o CR_TextBox.o CR_UserCreation.o CR_CheckBox.o

DEPS = CarRental.hpp CR_Button.hpp CR_LoginMenu.hpp CR_TextBox.hpp CR_UserCreation.hpp CR_CheckBox.hpp

%.o: %.cpp $(DEPS)
    $(CXX) -c -o $@ $< $(CPPFLAGS)

CRC.exe: $(OBJ)
    $(CXX) -o $@ $^ $(CPPFLAGS)

.PHONY: clean

clean:
    del *.o *.exe

Thanks in advance!

EDIT: I was wondering why is it compiling everything in my directory if only 1 out 6 .hpp files are modified on one line? Is something wrong with my makefile or is that how it is?

1 Answers

why is it compiling everything in my directory if only 1 out 6 .hpp files are modified on one line? Is something wrong with my makefile or is that how it is?

"Wrong" might be too strong a word, but yes, the behavior you describe is a consequence of how your makefile is written.

This rule ...

%.o: %.cpp $(DEPS)
    $(CXX) -c -o $@ $< $(CPPFLAGS)

... says, roughly, that you can build .o files from corresponding .cpp files plus all the files named in variable DEPS. This implies that if that's the rule make selects for building a given .o file, and any of those prerequisites is newer than the target, then the target is out of date and needs to be rebuilt. You have named all your headers in DEPS and you have not provided any other rules for building .o files, so yes, if any of your headers changes, all of the .o files will be rebuilt.

The most simple-minded alternative would be to write a separate rule for each .o, naming the prerequisites of that file only. That is, the corresponding .cpp file and whichever headers it #includes, directly or indirectly.

But you can save yourself a little typing by instead removing the $(DEPS) part from your existing rule, and adding an additional rule for each .o that does not have a recipe but names all the header prerequisites for that file.

Or if, as it appears, you have consistent relationships between source file names and header names, you might do something like this:

CXX = g++
CPPFLAGS = -I.
LIBS = -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system  -lm

MAIN_OBJ = CR_Main.o 
MODULE_OBJS = CarRental.o CR_Button.o CR_LoginMenu.o CR_TextBox.o CR_UserCreation.o CR_CheckBox.o

$(MAIN_OBJ): CR_Main.cpp $(MODULE_OBJS:.o=.h)
    $(CXX) $(CPPFLAGS) -c -o $@ $<

%.o: %.cpp %.h
    $(CXX) $(CPPFLAGS) -c -o $@ $<

CRC.exe: $(MAIN_OBJ) $(MODULE_OBJS)
    $(CXX) -o $@ $^ $(LIBS)

# Extra dependencies (guesses for the sake of example):
CarRental.o CR_LoginMenu.o CR_UserCreation.o: CR_TextBox.h CR_CheckBox.h
# No recipe here

.PHONY: clean

clean:
    del $(MAIN_OBJ) $(MODULE_OBJS) CRC.exe

Ultimately, though, what you would really like to do is generate all the header dependencies automatically. That makes the project much easier to maintain once you get it initially set up. You can find lots of information about that on the web, some of it in the GNU make manual.

Related