beyblade
beyblade

Reputation: 13

Can someone explain this makefile to me?

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

Answers (3)

Jonathan Leffler
Jonathan Leffler

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

Roland Illig
Roland Illig

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

jcomeau_ictx
jcomeau_ictx

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

Related Questions