4
\$\begingroup\$

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 $@
\$\endgroup\$
7
\$\begingroup\$
  • Making sources?

    The line

    all: $(SOURCES) $(EXECUTABLE)
    

    asks make to build $(SOURCES), in this case helloWorld.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 from git/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, let make deduce; this is what it is good for.

    all: $(EXECUTABLE)
    

    is what you want.

  • Be consistent

    all depends on $(EXECUTABLE), but debug depends on helloWorld. 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 with make 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 #includes - 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 a CFLAGS: 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 as CXX and uses CXXFLAGS. The CC and CFLAGS are reserved for plain c.

\$\endgroup\$
2
  • \$\begingroup\$ Your first point, that all: $(SOURCES) asks make to build $(SOURCES) is fundamentally wrong. It's saying that all depends upon $(SOURCES). This is actually true, though it's basically pointless. You want to tell it that all 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\$ Jan 6 '16 at 5:24
  • \$\begingroup\$ @JerryCoffin unclear all right \$\endgroup\$
    – vnp
    Jan 6 '16 at 6:14
2
\$\begingroup\$
  • CFLAGS

    The CFLAGS are C-specific and you always want to use CXXFLAGS for C++ code. You can expand the CXXFLAGS 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 target

    It is a good idea to put the all and debug and clean to a .PHONY target as make can complain a bit about the file not being created.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.