A Tutorial on Portable Makefiles

Rules of Makefiles

Makefile Tutorial

GNU Make guidelines

BSD Makefile example

My C++ Makefile project

TODO: publish it!

TODO: Highlight some interesting parts

Response to Make critics

Make commands aren't documented

When using Make, the Makefile and other source code is all the documentation that is provided.

Definitely not self-documenting, but we can have something like this:

    @echo "usage: make [OPTIONS] <target>"
    @echo "  Options:"
    @echo "    > VERBOSE Show verbose output for Make rules. Default 1. Disable with 0."
    @echo "    > SANITIZER Compile with GCC sanitizer. Default none. Options: address, thread, etc."
    @echo "Targets:"
    @echo "  debug: Builds all with debug flags"
    @echo "  release: Build with optimiser"
    @echo "  test: Build test executable"

Makes does not come with batteries included

Want to interact with a web API? You need to have cURL installed. Want to parse a text or configuration file? You’ll need awk or sed.

What is the alternative here? How does a tool like invoke solves this? pip install requests?

To check if an executable is installed we can use something like this:

CPPCHECK = cppcheck

define check_exec
    @command -v $(1) >/dev/null || (echo ERROR: $(1) not found in path >&2; exit 1)

    $(call check_exec, $(CPPCHECK))

(??? or use $(error text…))

Make does not support cross platform builds

Want to make the CLI cross platform? You’ll need to handle differences between Windows, Mac and Linux packages and their shell quirks.

Ouch. This hits hard.

Make is hard to debug

With this:

    @echo $* = $($*)

We can at least print the variables:

djen at xps in ~/example-cpp-project
make print-CXXFLAGS
CXXFLAGS = -std=c++17 -I/usr/include/png++
djen at xps in ~/example-cpp-project
make SANITIZER=thread print-CXXFLAGS
CXXFLAGS = -std=c++17 -I/usr/include/png++ -fsanitize=thread


In Memfault’s codebase, we have around 100 tasks, most of which are namespaced under general top-level modules.

We can organise code in separate files MyModule.include and have them included.


As a task runner or project CLI

Invoke with examples

As a build system for cross platform targets

CMake, Meson


Is CMake really the “cpp standard”? Check out the Rise of Meson.


Updated 02 January 2023