Ok this is the first makefile I've ever written. I it works and that's about it. Things that I was wondering if if I can specify where the object files go. It looks really bad with all the .o files cluttering the working folder. I was thinking a src folder and maybe a obj folder? Is there a better naming convention for Compiler_flags and c_compiler_flags? Also is there other ways of optimizing the makefile? Thanks all help is extremely appreciated.
OBJS = close.o init.o main.o texture.o load_media.o
CC = g++
COMPILER_FLAGS = -w
C_COMPILER_FLAGS = -c -w
LINKER_FLAGS = -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf
OBJ_NAME = run
all : exe
debug : COMPILER_FLAGS += -g
debug : C_COMPILER_FLAGS += -g
debug : exe
exe : $(OBJS)
$(CC) $(OBJS) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OBJ_NAME)
close.o : isolation.h close.cpp
$(CC) $(C_COMPILER_FLAGS) $(LINKER_FLAGS) close.cpp
init.o : isolation.h init.cpp
$(CC) $(C_COMPILER_FLAGS) $(LINKER_FLAGS) init.cpp
main.o : isolation.h main.cpp
$(CC) $(C_COMPILER_FLAGS) $(LINKER_FLAGS) main.cpp
texture.o : isolation.h texture.h texture.cpp
$(CC) $(C_COMPILER_FLAGS) $(LINKER_FLAGS) texture.cpp
load_media.o : isolation.h load_media.cpp
$(CC) $(C_COMPILER_FLAGS) $(LINKER_FLAGS) load_media.cpp
clean:
\rm *.o *~ run
1 Answer 1
There is no need to pass linker flags to the compile stage. You only them when you link the final executable.
Traditionally (aligned with
make
defaults) the flags variables areCFLAGS
for C compiler,CXXFLAGS
for C++ compiler, andLDFAGS
for the link stage specifics. It is not recommended however to have-c
as a part ofCFLAGS
: theCFLAGS
can be reused for non-compile action (e.g. dependency generation as described below).exe
is a phony target (and better be specified as such); a file namedexe
is never created, so it is never up to date, and the makefile forces linking even if nothing has been changed. I recommend to change the link recipe to$(OBJ_NAME): $(OBJS) ....
Stem rules let you DRY:
%.o: %.cpp $(CC) $(CXXFLAGS) $<
For a separate build directory you may look at
VPATH
; I prefer to to point it explicitly in the stem rule:$(BUILD)/%.o: %.cpp $(CC) -o $@ $(CXXFLAGS) $<
As a side note, I'd go one step further, and separate debug and release builds.
Dependency generation. The stem rules above do not specify
#include
dependencies. Withgcc
it is easy to automate.-M
family of flags:$(BUILD)/%.d: %.cpp $(CC) -o $@ -MM -MT $(CXXFLAGS) $<
create a makefile fragment which you'd
include
in your makefile.Since the dep and obj file names mirror the source file names (only the extension differs) it is recommended to generate them using the
patsubst
function.Never use
-w
. Warnings are your friends. I highly recommend passing at least-Wall -Wextra
.Putting it (almost) all together,
SRC = close.cpp init.cpp main.cpp texture.cpp load_media.cpp OBJ = $(patsubst %.cpp,$(BUILD)/%.o,$(SRC)) DEP = $(patsubst %.cpp,$(BUILD)/%.o,%(SRC)) TARGET = run $(BUILD)/%.o: %.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< $(BUILD)/%.d: %.cpp $(CXX) -MM -MT -o $@ $(CXXFLAGS) $< -include $(DEP) $(BUILD)/$(TARGET): $(OBJ) $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $(OBJ)