Pattern rules and built-in rules

Make · Practical · 12 min

Pattern rules are how a Makefile scales from two files to two hundred without growing.

A pattern rule uses % to match any non-empty stem:

build/%.o: src/%.c
	$(CC) $(CFLAGS) -c $< -o $@

To build build/net.o, make matches the stem net, looks for src/net.c and runs the recipe with $@ and $< filled in. One rule now covers every source file.

Combine it with variables listing the objects, usually computed from the sources:

SRC := $(wildcard src/*.c)
OBJ := $(SRC:src/%.c=build/%.o)

make also has built-in implicit rules. It already knows how to make x.o from x.c with $(CC) $(CPPFLAGS) $(CFLAGS) -c, and how to link x from x.o. That's why a Makefile containing only app: app.o can work. make -p prints all of them.

Built-in rules are convenient for tiny projects but surprising in bigger ones, and they slow make down by trying many candidate rules. Many projects disable them with MAKEFLAGS += --no-builtin-rules and an empty .SUFFIXES: line, and write explicit pattern rules instead.

Static pattern rules restrict a pattern to a list of targets: $(OBJ): build/%.o: src/%.c. They're more explicit and fail loudly when a source is missing.

Example

CC     := cc
CFLAGS := -Wall -O2
SRC    := $(wildcard src/*.c)
OBJ    := $(SRC:src/%.c=build/%.o)

MAKEFLAGS += --no-builtin-rules
.SUFFIXES:

build/app: $(OBJ)
	$(CC) -o $@ $^

build/%.o: src/%.c
	@mkdir -p $(@D)
	$(CC) $(CFLAGS) -c $< -o $@

.PHONY: clean
clean:
	rm -rf build

# with src/main.c and src/util.c:
# $ make
# cc -Wall -O2 -c src/main.c -o build/main.o
# cc -Wall -O2 -c src/util.c -o build/util.o
# cc -o build/app build/main.o build/util.o

Remember

  • %.o: %.c matches any stem; $< and $@ fill in the names
  • Derive object lists from sources with $(SRC:src/%.c=build/%.o)
  • make has built-in rules; --no-builtin-rules makes builds explicit

Watch out for

  • A pattern rule silently not applying because the prerequisite path is wrong; make then reports 'No rule to make target'.

Check yourself

  1. With the rule out/%.html: pages/%.md, what is the stem when building out/about.html?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.gnu.org/software/make/manual/make.html#Pattern-Rules