2
\$\begingroup\$

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
\$\endgroup\$
4
\$\begingroup\$
  • 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 are CFLAGS for C compiler, CXXFLAGS for C++ compiler, and LDFAGS for the link stage specifics. It is not recommended however to have -c as a part of CFLAGS: the CFLAGS 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 named exe 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. With gcc 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)
    
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.