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

Started by
5 comments, last by johnstanp 14 years, 8 months ago
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.
Advertisement
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.

This is what I get when I create the following makefile:
CC = g++DEBUG = -gCPPFLAGS = -Wall -O3 $(DEBUG)LDFLAGS = -lGL -lGLU -lSDLSRCDIR = srcINCDIR = includeOBJDIR = obj$(BUILD)/%.o: $(SRCDIR)%.cpp $(INCDIR)/%.hmain:	$(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
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 filesOBJECTS = $(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 $@ $<

Stephen M. Webb
Professional Free Software Developer

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 -WallLDFLAGS = -lGL -lGLU -lSDLINCDIR = includeSRCDIR = srcOBJDIR = obj# Define a list of object files derived from a list of .cpp source filesOBJECTS = $(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.
Doing this, my project now compiles;

CXX = g++CXXFLAGS = -g -O3 -WallLDFLAGS = -lGL -lGLU -lSDLINCDIR = includeSRCDIR = srcOBJDIR = obj# Define a list of object files derived from a list of .cpp source filesOBJECTS = $(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
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]

This topic is closed to new replies.

Advertisement