Sign in to follow this  

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

This topic is 3044 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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

This topic is 3044 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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