0
votes

Im currently trying to improve the makefile im using to build my c++ project using the sfml-framework. The folder structure of my project currently looks like this:

  • Src/Header for Header Files
  • Src/Source for .cpp Files
  • Bin/ for the .exe
  • Lib/ for the sfml library

My current makefile:

CC  = g++ -g    

SRC = Src/Source/  

BIN = Bin/    

INC = -I Lib/SFML/include/ -I Src/Header/    

LIB = -L Lib/SFML/lib/ -lsfml-graphics-d -lsfml-window-d -lsfml-system-d

EXE = Test     

SOURCEFILES = $(SRC)Main.cpp $(SRC)Menu.cpp $(SRC)Button.cpp

OBJ = $(SOURCEFILES:.cpp=.o)

all: $(SOURCEFILES) $(EXE)

$(EXE) : $(OBJ)
    $(CC) -o $(BIN)$(EXE).exe $(OBJ) $(LIB)

.cpp.o:
    $(CC) -c $< $(INC) -o $@

This makefile works fine, however there are a few things i would like to improve but could not get to work.

  1. It's currently nessecary to add all cpp files manually to the list of source files. Since the project is most likely going to grow fast in terms of file count and i kind of want to split the source files into different subdirectories this is going to be a mess very soon. I tried to get all cpp files in a directory with $(wildcard Src/Source/*.cpp) instead of listing them individually but it failed to even execute the makefile. What am i missing there?

  2. With my current makefile all .o files are placed at the same location as the .cpp file which is also something i dont really want. Is there a way to output all .o files in a extra \obj\ directory and link it into the .exe from there?

Also since this is the first time im writing a makefile if there are some general improvements to my approach any advice is appreciated aswell.

2
I can't answer your question appropriately but just want to mention, that cmake might be a good alternative instead of writing Makefiles manually.rbf
Im am using Visual Studio Code for my project so i was looking for a way to compile it from withing the build task ( Currently looks like this : "-f.vscode/Makefile" ). From my understanding, cmake is able to produce makefiles. So that would mean i have to generate a new one with cmake every time i add new files to my project which would be kind of the same sort of issue im trying to get out of my makefile. Or am i missing something there?Eric
You can specify in cmake also globs using wildcards, so that is not a big problem.rbf

2 Answers

0
votes
  1. wildcard should work:

    SOURCEFILES = $(wildcard $(SRC)/*.cpp)
    
  2. But if you plan to have your source files in various subdirectories of Src/Source/, it will not work that well. Use the find utility instead, thanks to the shell make function. And yes, you can store all your object files in a separate directory:

    CC  = g++ -g
    SRC = Src/Source/
    OBJ = Obj/
    BIN = Bin/
    INC = -I Lib/SFML/include/ -I Src/Header/
    LIB = -L Lib/SFML/lib/ -lsfml-graphics-d -lsfml-window-d -lsfml-system-d
    EXE = $(BIN)Test.exe
    
    SOURCEFILES = $(shell find $(SRC) -type f -name *.cpp)
    OBJECTFILES = $(patsubst $(SRC)%.cpp,$(OBJ)%.o,$(SOURCEFILES))
    
    all: $(SOURCEFILES) $(EXE)
    
    $(EXE): $(OBJECTFILE)
        $(CC) -o $@ $^ $(LIB)
    
    $(OBJ)%.o: $(SRC)%.cpp
        mkdir -p $(dir $@)
        $(CC) -c $< $(INC) -o $@
    

Note that I also modified your EXE definition such that the corresponding rule is a real files-to-file make rule and uses the $@ and $^ automatic variables.

1
votes

I'm kinda suprised that wildcard doesn't work for you, any error codes you could share?
Usually I write my SRCS and OBJS variables like this:

SRCS = $(wildcard src/*.cpp) \
       $(wildcard test/*.cpp)
OBJS = $(patsubst %.cpp,$(BINDIR)/%.o,$(SRCS))

And to build your object files into another directory you could write something like this:

$(BINDIR)/%.o: %.cpp
    $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@