Makefiles, how can I use them? [closed]

The question of when to use a Makefile is a matter of opinion. Certainly you can use some alternative builder (like e.g. omake or ninja, but there are many others). You certainly want some building system as soon as you have more than one translation unit in your software. If using make the Makefile describes the build process by detailing dependencies. Often, building you program is just done thru the simple make command.

Read more about C++ programming, and some C++ reference, for the terminology (perhaps also the C++11 standard n3337). See also this draft report.

Some utilities, e.g. cmake, qmake, automake, etc… are Makefile generators. They generate a complex Makefile which is usually not using all the features of GNU make.

If you decide to use make, I recommend using GNU make (this is also an opinion). In that case, read carefully its documentation, which I find quite readable and which contains a good tutorial. Don’t forget to use a recent version: the version 4.0 of GNU make was released in october 2013 and brings a lot of interesting new features (plugins, and most importantly extensibility thru guile) whih are interesting for complex builds.

To debug complex Makefile-s consider using remake (notably as remake -x).

In practice, GNU make has a lot of built-in rules. You get them with make -p; so use them.

You may also choose to code for the POSIX make utility (which is a standard specification, but less powerful than GNU make, which can be configured to follow the POSIX spec).

How to code a Makefile is a matter of taste, and of software complexity. If you have 2 or 3 *.cc files with a single .h common header, you don’t want all the fancy tricks (e.g. automatic dependencies, as provided by GCC and make) that are worth using on a software of many hundreds source files (and sometimes C++ source code is generated, e.g. by ANTLR, or by GNU bison, or by SWIG, by Qt moc, or by your own metaprogramming script, so the build system has to know that; for an example, see also RefPerSys).

Here is a tiny GNU Makefile to help you:

## file Makefile
CXX= g++
CXXSOURCES= main.cc other.cc
CXXOBJECTS= $(patsubst %.cc, %.o, $(CXXSOURCES))
OPTIMFLAGS= -g -O
PACKAGES= glib-2.0
PKGCONFIG= pkg-config
CXXFLAGS= -std=c++11 -Wall $(OPTIMFLAGS)
CPPFLAGS:=  $(shell $(PKGCONFIG) --cflags $(PACKAGES))
LIBES:= $(shell $(PKGCONFIG) --libs $(PACKAGES)) -ldl
.PHONY: all clean

all: myprog
myprog: $(CXXOBJECTS)
    $(LINK.cc) -rdynamic $^ $(LIBES) -o $@

$(CXXOBJECTS): yourheader.h

clean:
    $(RM) *.o *.so *.orig *~ myprog core* *.hh.gch
## eof Makefile

I don’t claim it is a perfect example (it is not). Be careful, tabulations are significant for make and I am not able to type them above. You’ll use make all (or just make) to build your program, and make clean to remove non-source files.

For obscure reasons, sometimes Makefile may be generated using autotools or cmake. For simple programs, it might not worth the effort to learn how to use them.

There are some few cases when GNU make is not worthwhile or appropriate: in MELT I nearly gave up using it (by calling some autogen generated shell script from it) because it is a bootstrapped language where a set of C++ files is generating itself from a set of MELT files, so you have a multiple to multiple quasi-circular dependency relation. Probably using a GUILE extension could have helped a lot. But such nightmare situations are rare.

PS: I answered as a Linux user; don’t know what applies -or not- to Windows which I never use. See also these hints about C or C++ programming on Linux.

PS2: Paul Evans’ answer is relevant: don’t write your own Makefile, copy some existing one to suit your needs.

Leave a Comment