Your First Makefile
Scope: the three parts of a rule — target, prerequisites, recipe — and the tabs rule that trips up every beginner exactly once.
The three parts
A Makefile is a list of rules. Each rule has three parts:
hello:
echo "Hello, Make!"
- Target (
hello:) — the thing you want to make, or the name of a task. - Prerequisites — files the target depends on. This rule has none yet.
- Recipe — the shell commands that build the target, one per line, each starting with a tab.
Run it:
$ make
echo "Hello, Make!"
Hello, Make!
Two things to notice. First, Make echoes each command
before running it — that's the echo "Hello, Make!"
line, then the actual output. (The @ prefix silences
the echo; see Automatic Variables.)
Second, running make with no arguments builds the
first target in the file — the default goal.
Now add a prerequisite:
greeting.txt:
echo "Hello, Make!" > greeting.txt
hello: greeting.txt
cat greeting.txt
$ make hello
echo "Hello, Make!" > greeting.txt
cat greeting.txt
Hello, Make!
Make built greeting.txt first (because hello needs
it), then ran hello's recipe. That's dependency order,
and it's the whole engine. (Plain make would have built
only greeting.txt — the first rule is the default
goal — so the target is named explicitly here.)
The tabs rule
Recipe lines must start with a tab character — not spaces, not "looks indented." This is Make's most famous quirk, and it bites everyone once. With four spaces instead of a tab:
$ make
Makefile:2: *** missing separator. Stop.
"Missing separator" means "I expected a tab and didn't find one." The fix is always the same: delete the leading whitespace and press Tab. Most editors can be told to keep tabs in Makefiles — and the surest defense is the one in this guide's README: type your recipes.
Check: cat -A Makefile shows tabs as ^I:
$ cat -A Makefile
hello:$
^Iecho "Hello, Make!"$
If you see spaces instead of ^I before a recipe line,
that's your bug.
Naming the file
Make looks for GNUmakefile, then makefile, then
Makefile, in that order, and uses the first one it
finds. Makefile with a capital M is the convention.
To use a different name:
$ make -f my-rules.mk