I had to create this makefile to build and debug a C++ console app. I just need some hints and tips on how I can organize my makefile.
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=helloWorld.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=helloWorld
all: $(SOURCES) $(EXECUTABLE)
debug: CXXFLAGS += -DDEBUG -g
debug: CCFLAGS += -DDEBUG -g
debug: helloWorld
clean:
rm *o helloWorld
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
2 Answers 2
Making sources?
The line
all: $(SOURCES) $(EXECUTABLE)
asks
make
to build$(SOURCES)
, in this casehelloWorld.cpp
. Is it possible to build it? Strictly speaking there are situations when you do want to build the source file (e.g. fetch it fromgit/cvs/sccs
) but it is not applicable here: no rule is provided. Generally you don't want to build something which doesn't depend on anything. In any case, letmake
deduce; this is what it is good for.all: $(EXECUTABLE)
is what you want.
Be consistent
all
depends on$(EXECUTABLE)
, butdebug
depends onhelloWorld
. Once you defined a macro, use it everywhere.Synonymous targets
Consider the scenario:
make
;./helloWold
; something goes wrong and you want to debug;make debug
: everything is up to date. To have a debug build you must intervene withmake clean
. A good practice is to separate debug and release builds into different directories.Automatic dependencies
In your example the
.o
file depends only on a corresponding.cpp
. In real life the.cpp
has some#include
s - and the.o
must depend on them all. Otherwise you will end up with an inconsistent build. Listing the.h
dependencies manually is tedious and error prone. The standard practice is to let the compiler generate them automatically. For example,g++
has-MM
,-MT
, etc options just for this purpose:DEPS := $(SOURCES:.cpp=.d) .cpp.d: $(CC) $(CXXFLAGS) -MM -MT -o $@ $< -include $(DEPS)
-c doesn't belong to CFLAGS
-c
is typically not listed in aCFLAGS
: you may want to generate various outputs (e.g. preprocessed source, assembly source, dependencies, documentation, etc) with the same set of flags. The way to achieve this is to specify-c
or-MM
or-S
or whatever separately from other flags, e.g..cpp.o: $(CC) -c $(CFLAGS) .... .cpp.s: $(CC) -S $(CFLAGS) ....
etc.
CC
Traditionally a
c++
compiler is referred asCXX
and usesCXXFLAGS
. TheCC
andCFLAGS
are reserved for plainc
.
-
\$\begingroup\$ Your first point, that
all: $(SOURCES) asks make to build $(SOURCES)
is fundamentally wrong. It's saying thatall
depends upon$(SOURCES)
. This is actually true, though it's basically pointless. You want to tell it thatall
depends on the executable, and make and then build the chain backward from the executable to the objects, and finally the source files. So your advice was right, but explanation...maybe not exactly wrong, but unclear at best. \$\endgroup\$Jerry Coffin– Jerry Coffin2016年01月06日 05:24:48 +00:00Commented Jan 6, 2016 at 5:24 -
\$\begingroup\$ @JerryCoffin unclear all right \$\endgroup\$vnp– vnp2016年01月06日 06:14:51 +00:00Commented Jan 6, 2016 at 6:14
CFLAGS
The
CFLAGS
are C-specific and you always want to useCXXFLAGS
for C++ code. You can expand theCXXFLAGS
a bit so that you can write really compact code.I use this set of compiler options for both C and C++:
-Wall -Wextra -Wfloat-equal -Wundef -Werror -fverbose-asm -Wshadow -Wpointer-arith -Wcast-align -Wstrict-prototypes -Wstrict-overflow=5 -Wwrite-strings -Wconversion
This answer is in the GCC manual so I won't explain what each option does. These options are present in any C or C++ project I start.
.PHONY
targetIt is a good idea to put the
all
anddebug
andclean
to a.PHONY
target asmake
can complain a bit about the file not being created.