Troubleshooting
Scope: the failures every Make beginner hits, symptom → cause → fix. Every error below was reproduced with GNU Make 4.3; the exact messages are quoted verbatim.
Makefile:2: *** missing separator. Stop.
Cause: a recipe line indented with spaces instead
of a tab. The 2 is the line number.
Fix: delete the leading whitespace on that line
and press Tab. Verify with cat -A Makefile — recipe
lines must show ^I, not spaces. See Your First
Makefile.
Makefile:1: *** recipe commences before first target. Stop.
Cause: a tab-indented line appears before any
target: line — usually a recipe that lost its
target during editing, or a stray indented line at
the top of the file.
Fix: find the indented line before the first target and either attach it to a rule or delete it.
make: *** No rule to make target 'frobnicate'. Stop.
Cause: you asked for a target Make doesn't know —
a typo (make claen), or a target that was never
defined.
Fix: check the spelling; make -p | grep '^frobnicate:'
confirms whether the target exists. With a prerequisite
variant — No rule to make target 'missing-file.txt',
needed by 'hello' — the prerequisite file doesn't
exist and nothing knows how to build it: create the
file or add a rule for it.
make: Circular b <- a dependency dropped.
$ make a
make: Circular b <- a dependency dropped.
make: Nothing to be done for 'a'.
Cause: a needs b and b needs a. Make
drops one leg of the circle and carries on — which
usually means nothing gets built.
Fix: break the cycle. One of the two dependencies is wrong: figure out which file is really produced from which, and remove the backwards edge.
make: 'clean' is up to date.
Cause: the classic missing-.PHONY trap. A file
named clean exists, so Make treats your task target
as a satisfied file target and skips the recipe —
silently, with exit code 0.
Fix: declare .PHONY: clean (and every other
task target). See .PHONY Targets.
Makefile:2: warning: undefined variable 'OUTDIR'
Cause: a misspelled (or never-set) variable —
$(OUTDIR) expanded to nothing, so files landed in
/file instead of $OUTDIR/file. Without
--warn-undefined-variables, there is no message at
all; the build just does the wrong thing quietly.
Fix: fix the name, or give it a default with
OUTDIR ?= somewhere. Run with
--warn-undefined-variables while developing.
The build does the wrong thing, quietly
No error, but stale results — the header-dependency bug from A Real C Build. A prerequisite is missing, so Make doesn't rebuild when it should.
Fix: make --trace shows why each target did or
didn't rebuild. Add the missing prerequisite. When
in doubt, make clean && make tells you whether the
Makefile is wrong or the build directory is stale.
Debugging order
make -n first (what would it do?), then --trace
(why?), then --warn-undefined-variables (typo?),
then make -p (what does Make believe?). See
Debugging Makefiles.