c++makefilemingwsdlvpath

Need to "make" twice when using vpaths


I've been getting into programming for the last 2 years or so and I'm finally "breaking out of the console" but as i do so, i also want to become independant from IDEs, therefore, i've been learning make but here's an issue i can't seem to find an answer to concerning "vpath"s

here is my makefile:

vpath %.o obj
vpath %.cpp src
vpath %.h inc

EXE = SDL_Game.exe
OBJS = SDL_Game.o Init.o EventHandler.o

INCDIR = -I"C:\SDL-1.2.15\include" -Iinc
LIBDIR = -L"C:\SDL-1.2.15\lib"
LIBS = -lmingw32 -lSDLmain -lSDL

CFLAGS = $(INCDIR) -Wall
LDFLAGS = $(LIBDIR) $(LIBS) -Wall -mwindows

all: $(EXE)

$(EXE): $(OBJS)
    g++ -o bin/$@ $^ $(LDFLAGS)

%.o: %.cpp
    g++ -o obj/$@ -c $< $(CFLAGS)

SDL_Game.o: SDL_Game.h
Init.o: SDL_Game.h
EventHandler.o: SDL_Game.h

.PHONY: clean

clean:
    rm -f bin/* obj/*

And as i use make the first time i use make i get this result:

C:\...\SDL_Test>make
g++ -o obj/SDL_Game.o -c src/SDL_Game.cpp -I"C:\SDL-1.2.15\include" -Iinc -Wall
g++ -o obj/Init.o -c src/Init.cpp -I"C:\SDL-1.2.15\include" -Iinc -Wall
g++ -o obj/EventHandler.o -c src/EventHandler.cpp -I"C:\SDL-1.2.15\include" -Iin
c -Wall
g++ -o bin/SDL_Game.exe SDL_Game.o Init.o EventHandler.o -L"C:\SDL-1.2.15\lib" -
lmingw32 -lSDLmain -lSDL -Wall -mwindows
g++.exe: error: SDL_Game.o: No such file or directory
g++.exe: error: Init.o: No such file or directory
g++.exe: error: EventHandler.o: No such file or directory
make: *** [SDL_Game.exe] Error 1

And i need to use make a second time to get the program to link. Why is that ? Should i not use "vpaths" Also this is what i get on the second make:

C:\...\SDL_Test>make
g++ -o bin/SDL_Game.exe obj/SDL_Game.o obj/Init.o obj/EventHandler.o -L"C:\SDL-1
.2.15\lib" -lmingw32 -lSDLmain -lSDL -Wall -mwindows

(Success)


Solution

  • You cannot use vpath to find object files. It can only be correctly used to find source files. No makefile recipe should ever build any target other than $@; that variable expands to the file that make expects your recipe to build. If it creates a different file then you're not upholding your end of the contract you've made with make.

    You need to change your makefile similar to this:

    OBJS = SDL_Game.o Init.o EventHandler.o
    
    EXE = bin/SDL_Game.exe
    

    and:

    $(EXE): $(addprefix obj/,$(OBJS))
            $(CXX) -o $@ $^ $(LDFLAGS)
    
    obj/%.o : src/%.cpp
            $(CXX) -o $@ -c $< $(CFLAGS)
    

    There are lots of different ways to do this but this is a start. You should also read http://make.mad-scientist.net/vpath.html