So, I'm making a program to test the efficiency of certain data structures. I have all the .h files and I made a very terrible makefile that probably is wrong, although it seems to work up to a point. Instead of making .o files it makes .gch files, so when it tries to acces all the .o files they are not found. This is my makefile
prog1: main.o dsexceptions.o BinarySearchTree.o SplayTree.o RedBlackTree.o AvlTree.o
g++ -Wall -g -o prog1 main.o dsexceptions.h.gch BinarySearchTree.h.gch SplayTree.h.gch RedBlackTree.h.gch AvlTree.h.gch
main.o: main.cpp AvlTree.h RedBlackTree.h SplayTree.h BinarySearchTree.h dsexceptions.h
g++ -Wall -g -c main.cpp
#shape.o: shape.cpp shape.h grid.h
# g++ -Wall -g -c shape.cpp
dsexceptions.o: dsexceptions.h
g++ -Wall -g -c dsexceptions.h
BinarySearchTree.o: BinarySearchTree.h dsexceptions.h
g++ -Wall -g -c BinarySearchTree.h
SplayTree.o: SplayTree.h dsexceptions.h
g++ -Wall -g -c SplayTree.h
RedBlackTree.o: RedBlackTree.h dsexceptions.h
g++ -Wall -g -c RedBlackTree.h
AvlTree.o: AvlTree.h dsexceptions.h
g++ -Wall -g -c AvlTree.h
clean:
rm -f main main.exe main.o dsexceptions.o BinarySearchTree.o SplayTree.o RedBlackTree.o AvlTree.o *.gch
You don't want to feed your .h files to the compiler. Only compile the .cpp file, which should include your .h files. (The .gch files are precompiled headers.) You don't need .o files for your headers, just #include them in your .cpp file.
prog1: main.o
g++ -Wall -g -o prog1 main.o
main.o: main.cpp AvlTree.h RedBlackTree.h SplayTree.h BinarySearchTree.h dsexceptions.h
g++ -Wall -g -c main.cpp
clean:
rm -f prog1 main.o
You already have the solution from bstpierre, but just for fun here's my version of your makefile:
CC = g++ -Wall -g -o $#
MODULE = AvlTree BinarySearchTree RedBlackTree SplayTree
OBJECTS = $(addsuffix .o,$(MODULES))
prog1: main.o dsexceptions.o $(OBJECTS)
$(CC) $^
main.o: $(addsuffix .h,$(MODULES))
$(OBJECTS) main.o : %.cpp %.h dsexceptions.h
$(CC) -c $<
clean:
rm -f main main.exe *.o *.gch
And just for good measure, here is my SConstruct, because SCons's so much better :)
Program('main.cpp') # Yeah, it's that simple :)
You can look at SCons here.
Related
I'm still learning how to set up a Makefile and I'm kind of lost here. I'm using windows and currently trying to fire up my Makefile for small C++ SDL project.
I have 3 .cpp files:
main.cpp
window.cpp
rect.cpp
As well as 2 extra header files:
Window.h
rect.h
So having trouble setting up everything on a Makefile
This is what i currently have:
CXXFLAGS = -Ideps/include -std=c++0x
LXXFLAGS = -Ldeps/lib -lmingw32 -lSDL2main -lSDL2
cup: main.o
g++ main.o -o cup $(LXXFLAGS)
main.o: main.cpp
g++ main.cpp -c $(CXXFLAGS)
window.o: window.cpp
g++ window.cpp -c
rect.o: rect.cpp
g++ rect.cpp -c
But I'm getting a bunch of undefined reference errors for my constructors on my command prompt.
Help please!
From the Makefile contents I read that cup binary is only created from main.o and it does not link window.o nor rect.o, which is where probably those missing references are defined. At the very least I would update the primary rule to say:
cup: main.o window.o rect.o
g++ $(LXXFLAGS) -o cup $^
Thus said, you could make even more use from implicit rules that are built into make, and, if following the standard naming for linking flags, the Makefile could be reduced even further to just a linking line (as compilation rules are implicit), e.g.:
$ cat Makefile
CXXFLAGS = -Ideps/include -std=c++0x
LDFLAGS = -Ldeps/lib
LDLIBS = -lmingw32 -lSDL2main -lSDL2
cup: main.o window.o rect.o
$(LINK.cc) $^ $(LDLIBS) -o $#
Output:
$ make
g++ -Ideps/include -std=c++0x -c -o main.o main.cpp
g++ -Ideps/include -std=c++0x -c -o window.o window.cpp
g++ -Ideps/include -std=c++0x -c -o rect.o rect.cpp
g++ -Ideps/include -std=c++0x -Ldeps/lib main.o window.o rect.o -lmingw32 -lSDL2main -lSDL2 -o cup
EXENAME = prog1
OBJS = link.o main.o
CXX = clang++
CXXFLAGS = -Wall -Wextra
LD = clang++
all : $(EXENAME)
$(EXENAME) : $(OBJS)
$(LD) $(OBJS) -o $(EXENAME)
main.o : link.h main.cpp
$(CXX) $(CXXFLAGS) main.cpp
link.o : link.h link.cpp
$(CXX) $(CXXFLAGS) link.cpp
clean :
-rm -f *.o $(EXENAME)
This is the make file I got but all the function in link can't be called in main. I tried many different ways doesn't work. This works
prog1: main.cpp link.h link.cpp
clang++ -Wall -Wextra -o prog1 main.cpp link.cpp
But I suppose is not the right way to do this?
It would help if you provided at least some of the errors you got (probably the first few).
Your compiler invocation for building object files is wrong. Without any other flags specified, the compiler will try to take all the input files and create an executable out of them. So this rule:
main.o : link.h main.cpp
$(CXX) $(CXXFLAGS) main.cpp
expands to this compilation line:
clang++ -Wall -Wextra main.cpp
The compiler will attempt to compile and link the main.cpp file (only, because that's all that's listed here) into an executable named a.out (by default).
You need to add the -c option to your compile lines if you want to build an object file rather than link a program:
main.o : link.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
Ditto for building link.o.
Even better would be to simply use make's built-in rules for compiling object files rather than writing your own; in that case your entire makefile could just be:
EXENAME = prog1
OBJS = link.o main.o
CXX = clang++
CXXFLAGS = -Wall -Wextra
all : $(EXENAME)
$(EXENAME) : $(OBJS)
$(CXX) $(CXXFLAGS) $(OBJS) -o $(EXENAME)
main.o : link.h
link.o : link.h
clean :
-rm -f *.o $(EXENAME)
Consider the following trivial Makefile. Notice that there are two classes with corresponding .h and .cpp files for each.
output: main.o class1.o class2.o
g++ main.o class1.o class2.o -o output
main.o: main.cpp
g++ -c main.cpp
class1.o: class1.cpp class1.h
g++ -c class1.cpp
class2.o: class2.cpp class2.h
g++ -c class2.cpp
clean:
rm *.o output
Is this Makefile robust? How can I make it more robust? Can someone provide a more robust version of this Makefile? It will be running on a 64 bit Red Hat Linux or CentOS machine.
If it matters, I am using:
-gcc --version 4.8.4 (From the GNU Compiler Collection)
-GDB version: GNU gdb (Ubuntu 7.7.1 -0ubuntu5~14.04.2) 7.7.1
I don't think your original makefile is far off the mark. I've just made a few additions:
Added a default all target - it's good to be explicit
Use the CXXFLAGS environment variable in all the calls to g++
Make main.o depend upon class1.h and class2.h as discussed
Specify that clean is a PHONY target just to be on the safe side if you add build artifact called clean
ALL := output
all : $(ALL)
output: main.o class1.o class2.o
g++ $(CXXFLAGS) main.o class1.o class2.o -o output
main.o: main.cpp class1.h class2.h
g++ $(CXXFLAGS) -c main.cpp
class1.o: class1.cpp class1.h
g++ $(CXXFLAGS) -c class1.cpp
class2.o: class2.cpp class2.h
g++ $(CXXFLAGS) -c class2.cpp
.PHONY : clean
clean:
rm *.o output
I would write something like
CXX = g++
# mandatory build flags
AM_CXXFLAGS = -Wall -W -std=gnu++11
# optional build flags
CXXFLAGS = -O2 -Werror
# mandatory link flags
AM_LDFLAGS = -Wl,-as-neeeded
output: main.o class1.o class2.o
${CXX} ${AM_LDFLAGS} ${LDFLAGS} $(filter %.o,$^) -o $#
%: %.cpp
${CXX} ${AM_CXXFLAGS} ${CXXFLAGS} $< -c -o $#
class1.o: class1.cpp class1.h
class2.o: class2.cpp class2.h
the *FLAGS are following automake notation: AM_* mean mandatory flags, the normal flags contain local settings (e.g. debugging or optimiziation).
Usually, AM_CPPFLAGS and CPPFLAGS with preprocessor flags (-I ...) should be used too but I omitted them here
the output target might need ${LIBS} too which have been omitted here
dependency tracking is more tricky and not implemented; you will have to play with -dM compiler option here...
When your program consists only of the listed 5 files, you can write
output_SOURCES = main.c class1.c class2.c class1.h class2.h
output: ${output_SOURCES}
${CXX} ${AM_CXXFLAGS} ${CXXFLAGS} ${AM_LDFLAGS} ${LDFLAGS} $(filter %.cpp,$^) -o $# ${LIBS}
directly.
EDIT:
For automatic dependency tracking, you can write
DEPGENFLAGS = \
-MD -MF ${#D}/.${#F}.d -MT '$#'
%: %.cpp
${CXX} ${DEPGENFLAGS} ${AM_CXXFLAGS} ${CXXFLAGS} $< -c -o $#
-include .deps.main.o.d
-include .deps.class1.o.d
-include .deps.class2.o.d
How can I make it more robust?
Use implicit rules, keep it simple.
LDLIBS+=-lstdc++
output: main.o class1.o class2.o
clean:
rm *.o output
I am doing a c++ project with multiple source files and trying to get used to using makefiles. I want to be able to debug this program with gdb. If I use the following command in Terminal to compile, it works fine:
g++ -o main -g *.cpp
But if I just call make it doesn't generate a debug file (the .dSYM file) even though it compiles the program fine. I assume this has something to do with creating the individual object files first. Here is my makefile:
all: main.o sort.o bubble.o quickSort.o rbs.o
g++ -g -o main *.o -Wall -O2
main.o: main.cpp
g++ -c main.cpp
sort.o: sort.cpp sort.h
g++ -c sort.cpp
bubble.o: bubble.cpp bubble.h
g++ -c bubble.cpp
quickSort.o: quickSort.cpp quickSort.h
g++ -c quickSort.cpp
rbs.o: rbs.cpp rbs.h
g++ -c rbs.cpp
clean:
rm *.o
How do I create the main.dSYM debug file when using a makefile like this?
If you want the debug files, you must compile all of the components with -g.
The crude way to do this would be to add -g to every object rule:
all: main.o sort.o bubble.o quickSort.o rbs.o
g++ -g -o main *.o -Wall -O2
main.o: main.cpp
g++ -c -g main.cpp
sort.o: sort.cpp sort.h
g++ -c -g sort.cpp
bubble.o: bubble.cpp bubble.h
g++ -c -g bubble.cpp
quickSort.o: quickSort.cpp quickSort.h
g++ -c -g quickSort.cpp
rbs.o: rbs.cpp rbs.h
g++ -c -g rbs.cpp
But that doesn't leave you the option of building without debug information. And there's a lot of redundancy in this makefile. Let's take this in stages. First, we put in automatic variables to simplify the rules:
all: main.o sort.o bubble.o quickSort.o rbs.o
g++ -g -o main $^ -Wall -O2
main.o: main.cpp
g++ -c -g $<
sort.o: sort.cpp sort.h
g++ -c -g $<
bubble.o: bubble.cpp bubble.h
g++ -c -g $<
quickSort.o: quickSort.cpp quickSort.h
g++ -c -g $<
rbs.o: rbs.cpp rbs.h
g++ -c -g $<
Now we see that all of the *.o rules have the same command, which reminds us that Make already knows how to build foo.o from foo.cpp, with a command that looks like:
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c
So all we have to do is add -g to CXXFLAGS, and we can omit the commands entirely:
CXXFLAGS += -g
all: main.o sort.o bubble.o quickSort.o rbs.o
g++ -g -o main $^ -Wall -O2
sort.o: sort.h
bubble.o: bubble.h
quickSort.o: quickSort.h
rbs.o: rbs.h
Now that that's in order, we can set up two top-level targets, main and debug, and change CXXFLAGS only for the latter:
debug: CXXFLAGS += -g
main debug: main.o sort.o bubble.o quickSort.o rbs.o
g++ -g -o $# $^ -Wall -O2
sort.o: sort.h
bubble.o: bubble.h
quickSort.o: quickSort.h
rbs.o: rbs.h
You can improve this even more, but that should get you started.
I'm trying to practice using Makefiles for a very simple program. The program files are:
main.cpp
other.cpp
other.h
I want the final executable to be Prog.
What happens when I run this is I get a main.o and other.o but no Prog.
What am I missing here?
## file Makefile
CXXOBJECTS= %.o
CXX= g++
CXXSOURCES= main.cpp other.cpp
CXXFLAGS= -std=c++11 -O2
Prog : main.o other.o
main.o : main.cpp
other.o : other.cpp other.h
## eof Makefile
You're almost there. You have the following:
Prog: main.o other.o ## these are your dependencies
g++ main.o other.o -o Prog
This should give you an executable called Prog. Though actually, a better makefile would be this:
CXXOBJECTS= %.o
CXX= g++
CXXSOURCES= main.cpp other.cpp
CXXFLAGS= -std=c++11 -O2
Prog: main.o other.o ## these are your dependencies
CXX main.o other.o -o Prog
main.o : main.cpp
CXX CXXFLAGS -c main.cpp
other.o : other.cpp
CXX CXXFLAGS -c other.cpp
Actually, you can make it even better, but I don't remember the syntactic sugar of makefiles off the top of my head (IDE's :P)