WhosSu
WhosSu

Reputation: 23

Speeding up makefile for SDL2

I'm currently working on an SDL2 project and the directory is structured in the following way

./
|__assets
|    |__*.png
|__src
|    |__physcis
|       |_*.cpp *.hpp
|    |__textures
|       |_obstacles
|           |_*.cpp *.hpp
|       |_constants
|           |_*.cpp *.hpp
|
|__Makefile

Currently, my makefile has a very simple structure Makefile:

ROOTDIR=src/
TXTURDIR = src/textures/constant/
OBSTACLEDIR = src/textures/obstacles/
PHYSDIR = src/physics/
OBJS = $(ROOTDIR)Main.cpp \
             $(ROOTDIR)WindowInit.cpp \
             $(ROOTDIR)Timer.cpp \
             $(ROOTDIR)GameLoop.cpp \
             $(PHYSDIR)Gravity.cpp \
             $(TXTURDIR)Texture.cpp \
             $(TXTURDIR)TextureContainer.cpp \
             $(TXTURDIR)Ball.cpp \
             $(TXTURDIR)Bob.cpp \
             $(TXTURDIR)Text.cpp \
             $(TXTURDIR)ScoreCounter.cpp \
             $(TXTURDIR)FPSCounter.cpp 

CC = g++

COMPILER_FLAGS = -g -o

LINKER_FLAGS = -lSDL2 -lSDL2_image -lSDL2_ttf
OUT = exe

all: $(OUT)
$(OUT): $(OBJS)
    $(CC) $(COMPILER_FLAGS) $@ $^ ${LINKER_FLAGS}

clean:
    rm exe

Is there any way to speed my making process up by only compiling certain folders when there is a change and then linking compiled sections together afterwards?

Upvotes: 1

Views: 115

Answers (1)

zwol
zwol

Reputation: 140669

Yes, this is the exact thing Makefiles are designed to do. Here's a set of changes to your existing Makefile that will do it:

Change your OBJS variable to refer to .o files instead of .cpp files. This turns your existing compilation rule into a link rule.

OBJS = $(ROOTDIR)Main.o \
         $(ROOTDIR)WindowInit.o \
         $(ROOTDIR)Timer.o \
         # ... etc ...

Make already knows how to create .o files from the .cpp files, thanks to its built-in set of implicit rules. However, you do need to adjust your configuration variable names to what Make's implicit rules expect. Don't put the -o option in the compiler flags, Make will add that itself.

# _instead of_ setting CC, COMPILER_FLAGS, LINKER_FLAGS
CXX = g++
CXXFLAGS = -g
LIBS = -lSDL2 -lSDL2_image -lSDL2_ttf

Adjust the link rule to match the adjusted variable names. (You don't have a CPPFLAGS right now but you may want it in the future.)

$(OUT): $(OBJS)
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $^ $(LIBS)

At the bottom of the file, add a set of rules without recipes, specifying the individual dependencies of each object file. This is how you arrange for things to get rebuilt when you change your header files, and it also works around a misfeature where sometimes Make will delete object files immediately after they are used. (For a project this size, it's easiest to keep track of which source files use which header files manually. When it gets big enough that you want to have the computer deal with that for you, look into automake.)

$(ROOTDIR)Main.o: $(ROOTDIR)Main.cpp foo.h bar.h
$(ROOTDIR)WindowInit.o: $(ROOTDIR)WindowInit.cpp foo.h bar.h
# ... etc ...

Change the clean target to clean up the object files as well (and while you're at it, use -rm -f instead of bare rm).

clean:
        -rm -f $(OUT) $(OBJS)

Add a .PHONY annotation at the very bottom of the file: this is not strictly necessary but will prevent weird things from happening if you ever have a file named 'all' or 'clean' for some reason:

.PHONY: all clean

And that's it, you're done.

Upvotes: 1

Related Questions