Makefile Pattern Rules & Dependency Generation

Pattern rules, wildcarding, implicit rules, static pattern rules, and generated dependency files in GNU make.

View
StandardDetailedCompact
Export
Copy the compact sheet, download it, or print it.
Download
`D` dense toggle · `C` copy all
## Implicit and pattern rules
Basic pattern rule
%.o: %.c
  cc -c $< -o $@

# Compile any `.c` file into a matching `.o` file.

Pattern rule with directories
build/%.o: src/%.c
  mkdir -p $(dir $@)
  cc -c $< -o $@

# Build objects into a separate output directory.

Static pattern rule
objects := main.o util.o api.o

$(objects): %.o: %.c
  cc -c $< -o $@

# Apply a pattern to a known target list.

Match and transform filenames
SRC := $(wildcard src/*.c)
OBJ := $(patsubst src/%.c,build/%.o,$(SRC))

# Create object names from source names.

Clear built-in suffix rules
.SUFFIXES:

# Reduce surprises by disabling legacy suffix rules.

## Automatic variables
$@ target name
archive.tar.gz: dist
  tar -czf $@ dist

# Expand to the current target file.

$< first prerequisite
%.o: %.c
  cc -c $< -o $@

# Expand to the first prerequisite.

$^ all prerequisites
app: main.o util.o
  cc $^ -o $@

# Expand to all prerequisites without duplicates.

$? newer prerequisites
libfoo.a: foo.o bar.o
  ar rcs $@ $?

# Expand to prerequisites newer than the target.

$* stem in pattern rules
build/%.min.js: src/%.js
  terser $< -o build/$*.min.js

# Use the matched stem from the target pattern.

dir and notdir with automatic vars
copy:
  @echo dir=$(dir $@) file=$(notdir $@)

# Extract target directory or file name.

## Wildcards and file discovery
wildcard function
SRC := $(wildcard src/**/*.ts)

# Expand glob patterns during parsing.

sort for deduplication
UNIQ_SRC := $(sort $(SRC))

# Sort and deduplicate a list of words.

filter files by pattern
TESTS := $(filter %_test.py,$(FILES))

# Keep only values that match a pattern.

filter-out values
SRC_NO_VENDOR := $(filter-out vendor/%,$(SRC))

# Exclude matches from a list.

foreach list expansion
PKG_TARGETS := $(foreach p,$(PACKAGES),test-$(p))

# Generate text for each item in a list.

## Generated dependency files
Generate C header dependency files
CFLAGS += -MMD -MP

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

-include $(OBJ:.o=.d)

# Have the compiler emit `.d` files while building objects.

Separate dependency file path
build/%.o: src/%.c
  cc -MMD -MP -MF build/$*.d -c $< -o $@

# Write depfiles beside objects using explicit flags.

Stamp-based dependency install
node_modules/.stamp: package-lock.json
  npm ci
  touch $@

build: node_modules/.stamp

# Rebuild only when lockfile changes.

Include generated files safely
-include $(DEPS)

# Load dependency files only if they exist.

## Archives and libraries
Build static library
libfoo.a: $(OBJ)
  ar rcs $@ $^

# Create an archive from object files.

Update archive with newer objects
libfoo.a: $(OBJ)
  ar rcs $@ $?

# Use `$?` to add only changed prerequisites.

Recommended next

No recommendations yet.