Foundations — Phony targets, pattern rules, implicit rules
Throughout this page, the parent note means the topic note this page hangs under: Phony targets, pattern rules, implicit rules. This page builds every symbol that note uses, from zero.
Before you can read a single line of the parent note, you need a small toolbox of ideas: files on disk, the clock stamp each file carries, what a target / prerequisite / recipe actually is, the TAB that recipes hide behind, the .PHONY declaration for jobs that aren't files, the % wildcard, and the four cryptic $@ $< $^ $* symbols. We build each from nothing, in the order they depend on each other.
1. A file, and its modification time (mtime)
WHAT it is: every file your computer stores has, alongside its contents, a little sticky note recording the last moment it was changed. That note is called the modification time, written mtime.
WHAT it looks like: think of each file as a box with a clock printed on the lid. Editing the file resets the clock to "now".

WHY the topic needs it: Make never opens your files to compare their contents — that would be slow. Instead it just reads the two clocks: "is the output's clock earlier than the input's clock?" If yes, the output is stale and must be rebuilt. Every rule in the parent note ultimately reduces to comparing these clocks.
2. Target, prerequisite, recipe — the anatomy of a rule
The parent note's atomic unit — recall "parent note" means the topic note this page sits under — is:
target: prerequisites
recipeThree plain-word meanings:
- target — the file you want to have (the thing to produce). Picture the box on the right of an arrow: the output.
- prerequisite — a file the target is made from. Picture the boxes on the left: the inputs. Also called a dependency.
- recipe — the shell command(s) that turn prerequisites into the target. Picture the machine on the arrow itself.

WHY the topic needs it: everything — phony targets, pattern rules, implicit rules — is a variation on this one shape. Phony targets are rules whose "target" is not really a file; pattern rules are rules where the target is a template; implicit rules are rules Make already knows. Master this shape and the rest are twists on it. See Dependency graphs and topological build order for how many rules chain together.
3. The invisible TAB
WHAT it is: the whitespace at the start of every recipe line must be a single TAB character, not spaces. A TAB and eight spaces look identical on screen but are different bytes to Make.
WHAT it looks like: the recipe is indented under its rule; that indentation is one press of the Tab key, drawn here as a distinct block.
WHY the topic needs it: this is the first error every beginner hits. Make uses the leading TAB to know "this line is a recipe, hand it to the shell." Spaces produce the infamous *** missing separator. Stop. The parent note flags it with a comment (# MUST be a TAB) precisely because it is silent and deadly.
4. The logic symbols: ⇔, ∨, ∃, ∈, >, <
The parent's rebuild formula uses a few maths symbols. Here is each in plain words so no line is a mystery — including the two-way arrow that opens the formula.
- — "if and only if": the left side is true exactly when the right side is. Picture a two-way arrow: cause and effect point both ways. This is the very first symbol in the formula, so we define it first.
- — "or": at least one of the two conditions holds. Picture two doors; walking through either triggers a rebuild.
- — "there exists": at least one item makes the following statement true. Picture scanning a shelf and stopping the instant you find one match.
- — "is a member of": reads " is one of the prerequisites." Picture picking one box out of the input pile.
- (greater-than) — "the left clock is later than the right clock." So says the input was edited after the output was built. The mirror symbol (less-than) says the opposite — the left clock is earlier; we use it in the "up to date" reading: means the input is older, so nothing needs rebuilding. Picture the wide side of the wedge always facing the bigger (later) clock.
Put together in English: rebuild the target if it is missing, OR if there exists any prerequisite whose clock is later than the target's clock; if every input's clock is the target's, skip.

WHY the topic needs it: this single line is the engine. Incremental compilation — rebuilding only what changed — is just this formula applied across a whole graph of files.
5. .PHONY — a target that is a job, not a file
WHAT it is: .PHONY is a special declaration line, .PHONY: name1 name2 ..., that tells Make "these target names do not stand for files on disk; they name actions." Common ones are clean, all, test.
WHAT it looks like: an ordinary target is a box holding a file with a clock. A phony target is a box with no file and no clock inside — just a label pointing at a command.
WHY the topic needs it: recall the rebuild formula from §4. A target with no prerequisites is "not missing and not older than anything," so Make declares it up to date and skips its recipe. If a stray file named clean ever appears in your directory, make clean would print 'clean' is up to date and never delete anything. Declaring .PHONY: clean forces Make to treat it as always out of date, so the recipe always fires.
.PHONY: clean all test
clean:
rm -f *.o program6. The % wildcard and the "stem"
WHAT it is: % is a placeholder that matches any non-empty run of characters. In a pattern rule it appears exactly once in the target and (at most) once in each prerequisite. The text it matches is called the stem.
WHAT it looks like: think of %.o: %.c as a stencil. Slide it over parser.o and the % slot lines up with parser; that captured parser is then poured into %.c to give parser.c. The same stem fills both blanks.

WHY the topic needs it: without %, a project with 100 .c files needs 100 nearly identical rules. The % collapses them into one template. This is the heart of both pattern rules (you write the template) and implicit rules (Make ships the template).
7. The automatic variables $@ $< $^ $*
Inside a recipe you cannot hard-code names like parser.o, because the template must work for every stem. So Make fills in four shorthand symbols at the moment a rule fires.
To make the values concrete, use this pattern rule that also lists the header as a fixed prerequisite (a %.o file usually depends on both its .c and a header):
%.o: %.c parser.h
$(CC) $(CFLAGS) -c $< -o $@Now suppose Make fires this rule to build parser.o. The stem is parser, so %.c becomes parser.c, and parser.h is the fixed second prerequisite.
For the rule above, building parser.o from parser.c and parser.h, the values become:
WHY the topic needs it: $< gives the compiler the one source file to compile; $@ names the output; $^ gives the linker every object at once. Miss the distinction and you either compile the header (error) or forget half your objects (link fails).
8. Built-in variables: CC, CFLAGS, CPPFLAGS, LDFLAGS
These are named boxes Make hands to implicit rules. See Makefile variables and expansion for how $(...) reads them and Compiler flags CFLAGS LDFLAGS for what each flag does.
CC— which C compiler to run (defaultcc). Not magic detection; just a variable.CFLAGS— flags for compiling (-Wall,-O2, ...).CPPFLAGS— flags for the preprocessor (-Iinclude paths,-Ddefines).LDFLAGS— flags for the linking step (-Llibrary paths).
WHY the topic needs it: implicit rules are written in terms of these boxes. Setting CC := clang changes the compiler everywhere at once — the foundation of Build reproducibility and the bridge to CMake and Ninja which generate these variables for you.
Prerequisite map
The diagram below is a top-down dependency map (each arrow reads "feeds into"). If your reader does not render Mermaid, here is the plain-words version: files carry clocks; clocks plus the rule shape give the rebuild formula; the formula plus the rule shape explain phony targets; the %/stem idea grows into pattern rules and their automatic variables; built-in variables feed implicit rules; every strand ends at the parent topic.
All arrows converge on the parent topic: the parent topic.
Equipment checklist
Test yourself — each line is a question ::: answer reveal. If any answer surprises you, re-read its section before opening the parent note.
What does mtime store, and why does Make prefer it over reading file contents?
stat() call instead of hashing the whole file.In target: prerequisites, which side is the output and which is the input?
Why must a recipe line start with a TAB, not spaces?
Translate "there exists p in prereqs with mtime(p) greater than mtime(target)" into English.
What does .PHONY: clean do, and why is it needed?
clean as an action, not a file, so Make ignores any same-named file and always runs the recipe.When %.o: %.c matches src/util.o, what is the stem and the prerequisite?
src/util (the % matches the slash too); the prerequisite becomes src/util.c.How many % are allowed in a pattern rule's target?
% in the target is an error.Give $@, $<, $^, $* in words.
In which rules is the stem $* actually meaningful?
Which variable chooses the compiler for implicit rules, and what is its default?
CC, default cc.