You are not logged in.

#26 2017-09-28 19:03:29

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,522
Website

Re: [SOLVED] (again) - Stumped on getting Makefile to look for *.o in obj/

JohnBobSmith wrote:

if [ ! -d obj ]; then mkdir obj; fi

First, you should never use those lines *anywhere*.  `mkdir -p $(ODIR)` as the first line of the compile rule works:

%.o: %.c
        mkdir -p $(ODIR)
        gcc -c -o $(ODIR)/$@ $<

"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#27 2017-09-28 19:38:55

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: [SOLVED] (again) - Stumped on getting Makefile to look for *.o in obj/

I feel like I'm once again reinventing the square wheel. Only this time each wheel has one less vertex than the previous, so that the last two wheels are now a line and a single vertex. Thank you so much Trilby for your continued help on the matter. I'm going to take my square wheels and see if I can make them round again. We are soooo close to finding the solution. I really want this to work. smile


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

#28 2017-09-28 20:03:20

progandy
Member
Registered: 2012-05-17
Posts: 5,190

Re: [SOLVED] (again) - Stumped on getting Makefile to look for *.o in obj/

I found these articles helpful when I was playing with out-of-tree builds using only (GNU)make.

http://make.mad-scientist.net/papers/ho … use-vpath/
http://make.mad-scientist.net/papers/mu … re-builds/


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#29 2017-09-29 15:44:32

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: [SOLVED] (again) - Stumped on getting Makefile to look for *.o in obj/

So after re-reading this thread I think I have found an adequate solution that is leaps and bounds better than when I first posted in my original post. Using Trilby's previous suggestion of putting sources in their own folder and using VPATH, we now have this makefile:

CXX = g++
CXXFLAGS = -Wall -g
PROG  = johntileengine
OBJS = AnimatedProps.o Bullet.o Camera.o Collision.o Config.o \
	Font.o main.o Mouse.o Player.o Shader.o SoundManager.o \
	Weapon.o World.o ResuplySystem.o Ai.o
LD = -lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio
VPATH = src

all: $(PROG)

%.o: %.cpp
	$(CXX) -c -o $@ $<

$(PROG): $(OBJS)
	$(CXX) -o $(PROG) $^ $(CXXFLAGS) $(LD)

clean:
	rm -f *.o $(PROG)

And the following outputs:

Fri Sep 29 jbs@dmb-gaming-laptop -> pwd
/home/jbs/cpp/john_tile_engine/src
Fri Sep 29 jbs@dmb-gaming-laptop -> ls
Ai.o             Collision.o  johntileengine  Mouse.o          SoundManager.o
AnimatedProps.o  Config.o     main.o          Player.o         src
Bullet.o         Font.o       Makefile        ResuplySystem.o  Weapon.o
Camera.o         include      makefile.bak    Shader.o         World.o
Fri Sep 29 jbs@dmb-gaming-laptop -> ls src/
Ai.cpp             Collision.cpp     main.cpp           Shader.cpp
AnimatedProps.cpp  Config.cpp        Mouse.cpp          SoundManager.cpp
Bullet.cpp         ControlPoint.cpp  Player.cpp         Weapon.cpp
Camera.cpp         Font.cpp          ResuplySystem.cpp  World.cpp
Fri Sep 29 jbs@dmb-gaming-laptop -> 

As you can see my separate source folder does not have any *.o files in it! A huge success!! big_smile From my observations (and I could be wrong, feel free to correct me) make is looking for *.o files from the same directory that it as called. So make was previously looking in src/ (the dir we run make from) for *.o files and finding none, recompiled everything to obj/ On the next compilation, seeing no *.o files in the src directory, make went ahead and recompiled everything to obj/ once more. Rinse and repeat. This is why I believe that I was having the issue of make recompiling everything earlier. Its a sound theory, in my opinion. Feel free to correct me if I am wrong. I welcome constructive criticism on the matter. With the current makefile in this post, make is called from src/ and the *.o files end up in src/, therefore make only compiles what is needed because it can now read the time stamps correctly.

Fri Sep 29 jbs@dmb-gaming-laptop -> make clean
rm *.o johntileengine
Fri Sep 29 jbs@dmb-gaming-laptop -> make
g++ -c -o AnimatedProps.o src/AnimatedProps.cpp
g++ -c -o Bullet.o src/Bullet.cpp
g++ -c -o Camera.o src/Camera.cpp
g++ -c -o Collision.o src/Collision.cpp
g++ -c -o Config.o src/Config.cpp
g++ -c -o Font.o src/Font.cpp
g++ -c -o main.o src/main.cpp
g++ -c -o Mouse.o src/Mouse.cpp
g++ -c -o Player.o src/Player.cpp
g++ -c -o Shader.o src/Shader.cpp
g++ -c -o SoundManager.o src/SoundManager.cpp
g++ -c -o Weapon.o src/Weapon.cpp
g++ -c -o World.o src/World.cpp
g++ -c -o ResuplySystem.o src/ResuplySystem.cpp
g++ -c -o Ai.o src/Ai.cpp
g++ -o johntileengine AnimatedProps.o Bullet.o Camera.o Collision.o Config.o Font.o main.o Mouse.o Player.o Shader.o SoundManager.o Weapon.o World.o ResuplySystem.o Ai.o -Wall -g -lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio
Fri Sep 29 jbs@dmb-gaming-laptop -> make
make: Nothing to be done for 'all'.

I'm actually very satisfied with this solution. We have solved the issue of putting *.o files in their own dir in a roundabout sort of way. I like this solution, so I'm marking the thread as [SOLVED]. Feel free to continue the discussion if need be. Thank you to everyone who helped me come to this solution! I really appreciate it! Bye now. big_smile


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

#30 2017-09-29 17:21:27

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,522
Website

Re: [SOLVED] (again) - Stumped on getting Makefile to look for *.o in obj/

So this is the "C" way that I mentioned in post 19.  Also note you can leave out the entire object file recipe as that is now identical to the implicit rule.  Also if you change the name of the LD variable to LDLIBS you can leave out the instructions for your PROG rule as that would then be the implicit recipe, in other words:

CXX      ?= g++
CXXFLAGS += -Wall -g
PROG      = johntileengine
OBJS      = AnimatedProps.o Bullet.o Camera.o Collision.o Config.o \
            Font.o main.o Mouse.o Player.o Shader.o SoundManager.o \
            Weapon.o World.o ResuplySystem.o Ai.o
LDLIBS    = -lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio
VPATH     = src

$(PROG): $(OBJS)

clean:
	rm -f *.o $(PROG)

I've also changed some of the variables to either conditionally set and/or append to them so the user's environment can have an influence if they prefer.

On another note, you could also use pkg-config:

LDLIBS    = $(shell pkg-config --libs sfml-all)

I'd frequently just make a variable DEPS which listed all the libraries I needed, then:

CFLAGS    += $(shell pkg-config --cflags ${DEPS})
LDLIBS    += $(shell pkg-config --libs ${DEPS})

This is particularly useful when your libs in turn have their own library dependencies.

Last edited by Trilby (2017-09-29 17:28:26)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Online

#31 2018-01-27 20:21:16

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: [SOLVED] (again) - Stumped on getting Makefile to look for *.o in obj/

Greetings!

I am re-opening this thread with some good news. I'm making progress towards having a Makefile that *actually* puts *.o in obj/. VPATH was a poor solution which demands an update. So here it is. My current Makefile:

CXX = g++
CXXFLAGS = -Wall -g
PROG  = johntileengine
#SRC = $(wildcard *.cpp)
#OBJS = $(SRC:.cpp=.o)
OBJS = obj/AnimatedProps.o obj/Bullet.o obj/Camera.o obj/Collision.o obj/Config.o \
	obj/Font.o obj/main.o obj/Mouse.o obj/Player.o obj/Shader.o obj/SoundManager.o \
	obj/Weapon.o obj/World.o obj/ResuplySystem.o obj/Ai.o obj/HealthBar.o \
	obj/Pickup.o
LD = -lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio
ODIR  = obj

all: $(PROG)

$(ODIR)/%.o: %.cpp
	mkdir -p $(ODIR)
	$(CXX) -c -o $@ $^

$(PROG): $(OBJS)
	$(CXX) -o $(PROG) $^ $(CXXFLAGS) $(LD)

clean:
	rm -f $(ODIR)/*.o johntileengine
	
.PHONY: clean

This solves the issue from post #29 about recompiling everything all the time. Lengthy example/proof of concept:

Sat Jan 27 jbs@dmb-gaming-laptop -> make clean
rm -f obj/*.o johntileengine
Sat Jan 27 jbs@dmb-gaming-laptop -> make
mkdir -p obj
g++ -c -o obj/AnimatedProps.o AnimatedProps.cpp
mkdir -p obj
g++ -c -o obj/Bullet.o Bullet.cpp
mkdir -p obj
g++ -c -o obj/Camera.o Camera.cpp
mkdir -p obj
g++ -c -o obj/Collision.o Collision.cpp
mkdir -p obj
g++ -c -o obj/Config.o Config.cpp
mkdir -p obj
g++ -c -o obj/Font.o Font.cpp
mkdir -p obj
g++ -c -o obj/main.o main.cpp
mkdir -p obj
g++ -c -o obj/Mouse.o Mouse.cpp
mkdir -p obj
g++ -c -o obj/Player.o Player.cpp
mkdir -p obj
g++ -c -o obj/Shader.o Shader.cpp
mkdir -p obj
g++ -c -o obj/SoundManager.o SoundManager.cpp
mkdir -p obj
g++ -c -o obj/Weapon.o Weapon.cpp
mkdir -p obj
g++ -c -o obj/World.o World.cpp
mkdir -p obj
g++ -c -o obj/ResuplySystem.o ResuplySystem.cpp
mkdir -p obj
g++ -c -o obj/Ai.o Ai.cpp
mkdir -p obj
g++ -c -o obj/HealthBar.o HealthBar.cpp
mkdir -p obj
g++ -c -o obj/Pickup.o Pickup.cpp
g++ -o johntileengine obj/AnimatedProps.o obj/Bullet.o obj/Camera.o obj/Collision.o obj/Config.o obj/Font.o obj/main.o obj/Mouse.o obj/Player.o obj/Shader.o obj/SoundManager.o obj/Weapon.o obj/World.o obj/ResuplySystem.o obj/Ai.o obj/HealthBar.o obj/Pickup.o -Wall -g -lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio
Sat Jan 27 jbs@dmb-gaming-laptop -> make
make: Nothing to be done for 'all'.
Sat Jan 27 jbs@dmb-gaming-laptop -> ls 
Ai.cpp             Bullet.cpp  Collision.cpp  Font.cpp       include         main.cpp  Mouse.cpp  Pickup.cpp  ResuplySystem.cpp  SoundManager.cpp  World.cpp
AnimatedProps.cpp  Camera.cpp  Config.cpp     HealthBar.cpp  johntileengine  Makefile  obj        Player.cpp  Shader.cpp         Weapon.cpp
Sat Jan 27 jbs@dmb-gaming-laptop -> ls obj/
Ai.o  AnimatedProps.o  Bullet.o  Camera.o  Collision.o  Config.o  Font.o  HealthBar.o  main.o  Mouse.o  Pickup.o  Player.o  ResuplySystem.o  Shader.o  SoundManager.o  Weapon.o  World.o
Sat Jan 27 jbs@dmb-gaming-laptop -> 

As we can see, because we listed it as a rule, make now finds the *.o files as intended. This is a perfect solution except for one thing: in my OBJS variable, I have to manually specify "obj/whatever.o" for each o file. I want to be able to use the commented out wildcard substitutions instead, so I can automatically grab all *.cpp/*.o files as I add more. The problem is I can't get the prefix to be obj/. I can only change the suffix *.cpp to be *.o. No amount of $(ODIR)/$(OBJS) or obj/$(OBJS) or other ideas have worked. It seems to me that specifying obj/ is mandatory, as it has to be part of the rule so make can find the files correctly. As I have mentioned earlier in this thread, I think that using cd obj/; doesnt work because make cant find the *.o files. Thats why obj/whatever.o must be specified in obj, as part of the rule. If we can solve this one last issue (using wildcards that have a prefix of obj/ and a suffix of *.o for my OBJS variable) that would be great!

Cheers!

JBS


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

#32 2018-01-27 20:38:34

progandy
Member
Registered: 2012-05-17
Posts: 5,190

Re: [SOLVED] (again) - Stumped on getting Makefile to look for *.o in obj/

Maybe you can use $(addprefix...)?

SRC = $(wildcard *.cpp)
OBJS = $(addprefix $(ODIR),$(SRC:.cpp=.o))

Last edited by progandy (2018-01-27 20:39:39)


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#33 2018-01-27 20:57:49

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: [SOLVED] (again) - Stumped on getting Makefile to look for *.o in obj/

Yes that worked perfectly! Thank you! Leave it to the make developers to put in all the extra useful features. big_smile smile

My intended and final solution to my all of my makefile troubles (for now at least) is this beautiful work of art:

CXX = g++
CXXFLAGS = -Wall -g
PROG  = johntileengine
ODIR  = obj
SRC = $(wildcard *.cpp)
OBJS = $(addprefix $(ODIR)/,$(SRC:.cpp=.o))
LD = -lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio

all: $(PROG)

$(ODIR)/%.o: %.cpp
	mkdir -p $(ODIR)
	$(CXX) -c -o $@ $^

$(PROG): $(OBJS)
	$(CXX) -o $(PROG) $^ $(CXXFLAGS) $(LD)

clean:
	rm -f $(ODIR)/*.o johntileengine
	
.PHONY: clean

Problem solved (again). Thanks for the lightning quick reply! smile


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

Board footer

Powered by FluxBB