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
A convenient way to specify in a "makefile" file, where to build object files
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:
but I want to know if a simpler scheme exits.
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.
$(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:
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
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 $@ $<
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 ):
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.
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:
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 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
Popular Topics
Advertisement