Makefile Cheat Sheet

Comprehensive GNU make and Makefile reference covering targets, prerequisites, recipes, variables, includes, conditionals, pattern rules, and command-line usage.

View
StandardDetailedCompact
Export
Copy the compact sheet, download it, or print it.
Download
`D` dense toggle · `C` copy all

Core make commands

Run make, choose files, select targets, and control execution.

Run default target

Run make using the default makefile and first target.

bashANYclidefaultbuild
bash
make
Notes

Reads `GNUmakefile`, `makefile`, or `Makefile` and builds the default goal.

Build a specific target

Run a named target from the makefile.

bashANYclitarget
bash
make test
Notes

Builds or executes the recipe for target `test`.

Use a specific makefile

Choose a file other than the default makefile names.

bashANYclimakefilefile
bash
make -f build/Makefile deploy
Notes

Use `-f` to point make at a specific file.

Run make in another directory

Change directory before reading the makefile.

bashANYclidirectory
bash
make -C services/api test
Notes

Useful in monorepos and wrapper scripts.

Parallel build

Build using multiple jobs.

bashANYcliparalleljobs
bash
make -j8
Notes

Allows multiple recipes to run in parallel when dependencies permit.

Dry run

Print commands without executing them.

bashANYclidry-rundebug
bash
make -n deploy
Notes

Great for inspecting what a target would do.

Touch targets only

Mark targets as updated without running recipes.

bashANYclitouch
bash
make -t
Notes

Useful for recovery and dependency graph alignment.

Question mode

Exit status indicates whether anything is out of date.

bashANYcliquestionci
bash
make -q
Notes

Handy in CI checks or wrapper scripts.

Trace recursive directories

Show enter/leave directory messages.

bashANYclirecursivedebug
bash
make --print-directory -C app test
Notes

Useful when debugging recursive make.

Enable debug output

Print internal decision-making details.

bashANYclidebugdiagnostics
bash
make --debug=b
Notes

GNU make supports several debug modes such as `a`, `b`, `v`, `i`, `j`, and `m`.

Warn on undefined variables

Emit warnings when undefined variables are expanded.

bashANYclivariablesdebug
bash
make --warn-undefined-variables
Notes

Very useful in large makefiles with many variables.

Print database

Dump parsed rules and variables.

bashANYclidatabasedebug
bash
make -p -n
Notes

Shows built-in rules, variables, and parsed state.

Targets, prerequisites, and recipes

Core makefile structure and everyday patterns.

Basic rule

Define a target, prerequisites, and recipe.

makefileANYrulestargetrecipe
makefile
build/app: main.o util.o
  cc -o build/app main.o util.o
Notes

A rule maps a target to prerequisites and the commands needed to update it.

Rule with multiple prerequisites

Rebuild target when any listed prerequisite changes.

makefileANYrulesprerequisitesautomatic-variables
makefile
bundle.js: app.js ui.js api.js
  cat $^ > $@
Notes

`$^` expands to all prerequisites and `$@` to the target name within the recipe.

Phony target

Create a target that does not represent a file.

makefileANYphonytarget
makefile
.PHONY: test

test:
  pytest -q
Notes

Use phony targets for commands like `test`, `clean`, and `deploy`.

Multiple targets one recipe

Attach the same recipe to multiple targets.

makefileANYrulesmultiple-targets
makefile
.PHONY: lint fmt
lint fmt:
  pnpm biome check .
Notes

Useful when several targets truly run the same command.

Order-only prerequisite

Require creation order without forcing rebuilds when the prerequisite timestamp changes.

makefileANYprerequisitesorder-onlydirectories
makefile
dist/app.js: src/app.js | dist
  cp $< $@

dist:
  mkdir -p dist
Notes

Prerequisites after `|` enforce order only.

Stamp file target

Track completion of a step using a timestamp file.

makefileANYstampdependenciesci
makefile
node_modules/.stamp: package-lock.json
  npm ci
  touch $@
Notes

A stamp file is often cleaner than making a phony install target rerun every time.

Clean target

Remove build artifacts.

makefileANYcleanphony
makefile
.PHONY: clean
clean:
  rm -rf dist build *.o
Notes

Classic maintenance target.

Set explicit default goal

Choose which target runs when the user invokes plain `make`.

makefileANYdefault-goalspecial-targets
makefile
.DEFAULT_GOAL := help
Notes

Clearer than relying on the first target in the file.

Variables and assignment

Recursive, simple, conditional, and shell-expanded variables.

Recursive variable

Expand later when used.

makefileANYvariablesassignment
makefile
SRC = $(wildcard src/*.c)
Notes

`=` creates a recursively expanded variable.

Simple variable

Expand immediately at assignment time.

makefileANYvariablesassignmentsimple
makefile
CURDIR_ABS := $(shell pwd)
Notes

`:=` is useful when you want shell commands or functions evaluated once.

Append to variable

Add text to an existing variable.

makefileANYvariablesappend
makefile
CFLAGS += -Wall -Wextra
Notes

Works with both recursive and simple variables.

Set if undefined

Assign only if variable is not already set.

makefileANYvariablesconditional
makefile
ENV ?= dev
Notes

Often used with environment overrides like `make ENV=prod deploy`.

Override from command line

Pass variable values when invoking make.

bashANYvariablesclioverride
bash
make IMAGE_TAG=2026.03.06 deploy
Notes

Command-line variables override normal makefile assignments.

Force override in makefile

Override even a command-line assignment.

makefileANYvariablesoverride
makefile
override CFLAGS += -g
Notes

Use sparingly when the makefile must enforce a setting.

Export variable to recipes

Pass a variable into the shell environment of recipe commands.

makefileANYvariablesexportenvironment
makefile
export AWS_PROFILE := prod-admin
Notes

Exported variables are inherited by recipe shells and recursive make invocations.

Stop exporting a variable

Prevent a variable from propagating to recipes and sub-makes.

makefileANYvariablesunexportenvironment
makefile
unexport DEBUG
Notes

Useful when a parent environment leaks unwanted values.

Inspect variable origin

See where a variable value came from.

makefileANYvariablesdiagnostics
makefile
$(info CC came from $(origin CC))
Notes

Origins include `default`, `environment`, `file`, `command line`, and more.

Inspect variable flavor

Check whether a variable is recursive or simple.

makefileANYvariablesdiagnostics
makefile
$(info CFLAGS flavor: $(flavor CFLAGS))
Notes

Useful when debugging unexpected expansions.

Includes and conditionals

Split makefiles and branch on environment or platform.

Include another makefile

Read another file while parsing.

makefileANYincludemodularity
makefile
include config.mk rules/*.mk
Notes

`include` is excellent for shared project fragments.

Optional include

Ignore missing include files.

makefileANYincludeoptional
makefile
-include .env.mk
Notes

Common for generated dependency files and local overrides.

ifeq conditional

Branch based on string equality.

makefileANYconditionalsifeq
makefile
ifeq ($(ENV),prod)
  API_URL := https://api.example.com
else
  API_URL := https://api.dev.example.com
endif
Notes

GNU make conditionals run during parsing, not execution.

ifdef conditional

Check whether a variable is defined.

makefileANYconditionalsifdef
makefile
ifdef CI
  TEST_FLAGS += --maxfail=1
endif
Notes

Useful for CI-vs-local behavior.

OS-specific include

Branch based on operating system or shell-provided variables.

makefileANYconditionalsplatform
makefile
ifeq ($(OS),Windows_NT)
  RM := del /Q
else
  RM := rm -f
endif
Notes

Portable projects often branch on Windows vs Unix-like behavior.

Special targets and behavior control

Targets that alter how make interprets rules and files.

Declare multiple phony targets

Mark non-file targets explicitly.

makefileANYspecial-targetsphony
makefile
.PHONY: all clean test lint format help
Notes

Prevents file name collisions and speeds make slightly by skipping implicit rule search.

Silent recipes

Suppress command echoing globally or per line.

makefileANYspecial-targetssilent
makefile
.SILENT:
# or prefix a line with @
Notes

Silence all recipes or use `@command` for individual lines.

Delete target on error

Remove a partially built target if the recipe fails.

makefileANYspecial-targetserrors
makefile
.DELETE_ON_ERROR:
Notes

Helpful for avoiding corrupt output files after failures.

One shell per recipe

Run all lines of a recipe in a single shell instance.

makefileANYspecial-targetsshell
makefile
.ONESHELL:

deploy:
  set -eu
  cd infra
  terraform apply -auto-approve
Notes

Without `.ONESHELL`, each recipe line runs in a separate shell.

Secondary expansion

Allow a second variable expansion for prerequisites.

makefileANYspecial-targetsexpansionadvanced
makefile
.SECONDEXPANSION:

$(OUT_DIR)/%.o: $$(SRC_DIR)/%.c
  cc -c $< -o $@
Notes

Advanced GNU make feature used with dynamic prerequisite lists.

Disable parallelism

Force serial execution for all or selected targets.

makefileANYspecial-targetsparallel
makefile
.NOTPARALLEL:
Notes

Useful for non-parallel-safe recipes.

Recommended next

No recommendations yet.