Sign in to follow this  
johnstanp

A convenient way to specify in a "makefile" file, where to build object files

Recommended Posts

Well, I have a project( written and compiled on windows ) and I want to compile it on Linux. Since that project is still a work in progress, I want to be able to recompile only the files I modify, hence the use of GNU Make. I've already used it but for small projects. Since I don't have the time to read the comprehensive documentation( or simply put, I am too lazy to do it ), I want to know a convenient way to "tell" make where to place the object files( ".o" ), generated during the compilation process. I want, for instance, to place all the ".o" files in an "obj/" directory. I thought doing it this way:
OBJS = Axis_aligned_box.o

CC = g++
DEBUG = -g
CPPFLAGS = -Wall -c $(DEBUG)
LDFLAGS = -Wall $(DEBUG) -lGL -lGLU -lSDL
SRCDIR = src/
INCDIR = include/
OBJDIR = obj/

Axis_aligned_box.o: $(INCDIR)Axis_aligned_box.h
	$(CC) $(CPPFLAGS) $(SRCDIR)Axis_aligned_box.cpp -o $(OBJDIR)Axis_aligned_box.o


but I want to know if a simpler scheme exits.

Share this post


Link to post
Share on other sites
I use a rule which reads approximately;

$(BUILD)/%.o: %.cpp %.h
$(CC) -ggdb -c $(CFLAGS) -o $(BUILD)/$*.o $<

{It generates dependency files and stuff along the way, which I've taken out for this example.}

The "%" is a wildcard matcher. Saves you writing a rule for every compileable file. You might want to say something like;

$(BUILD)/%.o: %.cpp $(INCDIR)/%.h

if your headers are in a different directory.

Share this post


Link to post
Share on other sites
This is what I get when I create the following makefile:

CC = g++
DEBUG = -g
CPPFLAGS = -Wall -O3 $(DEBUG)
LDFLAGS = -lGL -lGLU -lSDL
SRCDIR = src
INCDIR = include
OBJDIR = obj

$(BUILD)/%.o: $(SRCDIR)%.cpp $(INCDIR)/%.h

main:
$(CC) $(CPPFLAGS) $(LDFLAGS) -o $(BUILD)/$*.o $<







g++ -ggdb -c -Wall -O3 -o /.o
g++: pas de fichier à l'entrée
make: *** [main] Erreur 1

I'll translate it as:
g++: no input file
make: ***[main] Error 1

Share this post


Link to post
Share on other sites
Quote:
Original post by johnstanp
g++ -ggdb -c -Wall -O3 -o /.o
g++: pas de fichier à l'entrée

The default value of an undefined Make variable is an empty string.

Try using a rule like this (off the top of my head, untested).

# Define a list of object files derived from a list of .cpp source files
OBJECTS = $(addprefix $(OBJDIR),$(patsubst %.cpp,%o,$(wildcard $(SRCDIR)/*.cpp)))

# Provide an implicit dependency rule for building the objects.
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(INCDIR)/%.h
$(CXX) -c $(CXXFLAGS) -o $(OBJDIR)/$*.o $<

# Provide an explicit rule for building the application from the objects.
main: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $<

Share this post


Link to post
Share on other sites
I made some slight modifications to the code you, so kindly, provided( a "." and a "/" have been added in the line where the list of object files are derived ):


CXX = g++
CXXFLAGS = -g -O3 -Wall
LDFLAGS = -lGL -lGLU -lSDL
INCDIR = include
SRCDIR = src
OBJDIR = obj

# Define a list of object files derived from a list of .cpp source files
OBJECTS = $(addprefix $(OBJDIR)/,$(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp)))

# Provide an implicit dependency rule for building the objects.
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(INCDIR)/%.h
$(CXX) -c $(CXXFLAGS) -o $(OBJDIR)/$*.o $<

# Provide an explicit rule for building the application from the objects.
main: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $<

clean:
rm -f $(OBJDIR)/*.o



I have the following error:
make: *** Pas de règle pour fabriquer la cible « obj/src/Axis_aligned_box.o », nécessaire pour « main ». Arrêt.

make: *** No rule to build the target « obj/src/Axis_aligned_box.o », necessary for main. Stop.

Share this post


Link to post
Share on other sites
Doing this, my project now compiles;


CXX = g++
CXXFLAGS = -g -O3 -Wall
LDFLAGS = -lGL -lGLU -lSDL
INCDIR = include
SRCDIR = src
OBJDIR = obj

# Define a list of object files derived from a list of .cpp source files
OBJECTS = $(addprefix $(OBJDIR)/,$(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp)))

# Provide an implicit dependency rule for building the objects.
$(OBJDIR)/$(SRCDIR)/%.o: $(SRCDIR)/%.cpp $(INCDIR)/%.h
$(CXX) -c $(CXXFLAGS) -o $(OBJDIR)/$(SRCDIR)/$*.o $<

# Provide an explicit rule for building the application from the objects.
main: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $<

clean:
rm -f $(OBJDIR)/$(SRCDIR)/*.o

Share this post


Link to post
Share on other sites
It was compiling until g++ complained that it can't build the target « obj/src/main.o ».
This should be expected since main.cpp( the file where int main() is declared ), has no corresponding header file. I had to create one, containing all the necessary header files for main.cpp( the sole existence of main.h would have done the trick, after all )

And I made another correction. I had the following errors when compiling the project:

g++ -lGL -lGLU -lSDL -o main obj/src/Axis_aligned_box.o
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
obj/src/Axis_aligned_box.o: In function `Axis_aligned_box':
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
obj/src/Axis_aligned_box.o:/media/disk/Game/src/Axis_aligned_box.cpp:8: more undefined references to `ngn::Vector3::ZERO' follow
obj/src/Axis_aligned_box.o: In function `Axis_aligned_box':
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::Vector3(double, double, double)'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::ZERO'
obj/src/Axis_aligned_box.o:/media/disk/Game/src/Axis_aligned_box.cpp:8: more undefined references to `ngn::Vector3::ZERO' follow
obj/src/Axis_aligned_box.o: In function `Axis_aligned_box':
/media/disk/Game/src/Axis_aligned_box.cpp:8: undefined reference to `ngn::Vector3::Vector3(double, double, double)'
collect2: ld a retourné 1 code d'état d'exécution

The script only instructs g++ to build the final main binary with only one object, the first one.
I then modified the makefile this way:


main: $(OBJECTS)
$(CXX) $(LDFLAGS) $(OBJECTS) -o main






Man, you're my hero! :)

P.S: I would have thanked you a lot earlier, had I not generated a makefile with all the dependencies, by hand and made my project compile that way.

[Edited by - johnstanp on August 17, 2009 11:15:44 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this