Reputation: 13
I've been using c++ casually for a couple of months with a makefile I don't even remember where I got or if I did it myself (the actual structure it has. I know I've added some libraries and flags though):
SRC = filename.cpp
TARG = filename
CC = g++
CPPFLAGS = -g -Wall -Werror -Wextra -pipe -pedantic -Weffc++ -std=c++0x -O2 -Wno-unused-function `pkg-config --cflags opencv`
LDFLAGS = `pkg-config --libs opencv` -lboost_regex -lboost_filesystem
OBJ = $(SRC:.cpp=.o)
all: $(TARG)
clean:
rm -f *~ *.o $(TARG)
I wanted to use it to compile a class, but first I have to understand what is going on since I have to modify it a bit. Also, are there any bad practices in it?
Upvotes: 1
Views: 415
Reputation: 753705
If you want to compile a class instead of a program, you need to do a little surgery on the file. I'm assuming that you want an object file, not a library; the rules for libraries are more complex. But this should do the trick.
SRC = class.cpp
OBJ = $(SRC:.cpp=.o)
CC = g++
CPPFLAGS = -g -Wall -Werror -Wextra -pipe -pedantic -Weffc++ -std=c++0x -O2 \
-Wno-unused-function `pkg-config --cflags opencv`
LDFLAGS = `pkg-config --libs opencv` -lboost_regex -lboost_filesystem
DEBRIS = core a.out *~
all: $(OBJ)
class.o: class.h
clean:
rm -f $(DEBRIS) $(OBJ)
It is not immediately clear whether $(CPPFLAGS)
will automatically appear in the compilation or linking commands.
If you end up wanting to build the program from two files, then you use a hybrid:
SRC = filename.cpp class.cpp
OBJ = $(SRC:.cpp=.o)
PROGRAM = program
CXX = g++
CXXFLAGS = -g -Wall -Werror -Wextra -pipe -pedantic -Weffc++ -std=c++0x -O2 \
-Wno-unused-function `pkg-config --cflags opencv`
LDFLAGS = `pkg-config --libs opencv` -lboost_regex -lboost_filesystem
DEBRIS = core a.out *~
all: $(PROGRAM)
$(PROGRAM): $(OBJ)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ) $(LDFLAGS)
class.o: class.h
filename.cpp: class.h
clean:
rm -f $(DEBRIS) $(OBJ) $(PROGRAM)
Note that I've changed the macro for the C++ compiler from CC to CXX. The standards are not clear on the name for the C++ compiler. POSIX doesn't mention C++ in its description of make
. However, CC is clearly intended for compiling C rather than C++. That needn't stop your version of make
from using CC for C++ compilation, but it would be a little unusual. (GNU Make 3.81 on MacOS X 10.6.8 uses CXX for the C++ compilation.) The link line now uses $(CXXFLAGS)
(thanks to eriktous); it is still not clear whether the C++ source to object file compilation would do so. Ultimately, that's why you end up seeing makefiles with rules such as:
class.o: class.h
$(CXX) -c $(CXXFLAGS) $*.cpp
This guarantees that the compilation rule is what you see for this object file. You might write that as an old-fashioned but portable suffix rule (.cpp.o:
) instead; the POSIX specification for make
supports these. Or you might use the more modern but not necessarily quite as portable %.o : %.o
notation instead (not required by POSIX). Either of these replaces any previous (built-in) definition of how to compile an object file from C++ source.
.cpp.o:
$(CXX) -c $(CXXFLAGS) $*.cpp
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $*.cpp
I assume you are using opencv
(and some of Boost); if not, your compilation and linking flags include irrelevant options. The dependencies are guessed; make
will infer the dependency of the object file on the C++ source code, so I only listed header dependencies. But you may have many more if you're using opencv
and Boost.
(Makefiles not formally tested.)
Upvotes: 2
Reputation: 41625
It already looks good. You defined the proper variables, the file is short and readable, what else do you want?
In the clean
target, you could only remove $(OBJ)
instead of *.o
. And you should not remove your editor's backup files as part of the build process. I suggest this instead:
clean:
rm -f $(TARG) $(OBJ)
clean-all: clean
rm -f *~
# mark these targets as non-files.
.PHONY: all clean clean-all
Upvotes: 1
Reputation: 38432
when you type "make" with no args, it looks for the first recipe, something that starts in the first column with a colon after it. that would be all
, which tells it to build TARG. TARG is filename. Make is already configured on many systems to know what to do with .cpp files, so there is no specific recipe in this Makefile to do that. The OBJ construct is unused here, so no need to explain that; but what it means is "replace .cpp in SRC with .o", so OBJ would be filename.o.
Upvotes: 1