WHAT Make actually reasons about is a graph of files (a DAG — Directed Acyclic Graph). Each node is a file; an edge means "this file is built from that file."
This is recursive: before checking t(Pi), Make first ensures each Pi is itself up-to-date (build the prerequisites first). That's a post-order traversal of the dependency DAG.
Make uses the literal TAB as the separator that marks a line as a recipe; spaces give "missing separator" error.
Make's rebuild condition for target T
Rebuild if T doesn't exist OR any prerequisite is newer than T (t(P_i) > t(T)).
Difference between = and :=
= is recursive/lazy (expanded each use); := is simple/eager (expanded once at definition).
What does $@ mean?
The target name of the current rule.
What does $< mean?
The first prerequisite.
What does $^ mean?
All prerequisites, space-separated, duplicates removed.
What does $? mean?
Only the prerequisites newer than the target (the stale ones).
What does $* mean?
The stem matched by % in a pattern rule.
What does .PHONY do?
Declares a target as not a real file, so its recipe always runs even if a file by that name exists.
What does $(SRCS:.c=.o) produce?
A substitution reference replacing the .c suffix with .o in each word of SRCS.
In app: main.o utils.o, recipe $(CC) $^ -o $@, what links?
Links main.o and utils.o into app; $^=all objects, $@=app.
What traversal order does Make use on the dependency DAG?
Post-order — build prerequisites before the target.
Why use ?=?
Assign a variable only if it isn't already defined (good for overridable defaults).
Recall Feynman: explain to a 12-year-old
Imagine you're making a sandwich-building robot. You tell it: "To make a sandwich, you first need bread and filling." The robot is lazy in a smart way: if you already have a sandwich and nobody touched the bread or filling since, it won't waste time making another one. But if you bought fresh bread (newer than the sandwich!), it knows the old sandwich is out of date and builds a new one. The target is the sandwich, the prerequisites are bread and filling, and the recipe is "put filling between bread." The little symbols like $@ are just shortcuts so the robot can say "the thing I'm making" without writing its name again.
Make ek aisa tool hai jo aapke project ko smartly build karta hai — yaani jo file change hui hai sirf usi se jude hisse dobara compile karta hai, baaki ko chhod deta hai. Iska core funda ek hi hai: timestamp comparison. Agar output file (jaise main.o) apni source file (main.c) se purani hai, matlab source naya hai, to Make recipe chala ke output ko dobara banata hai. Agar output already naya hai, to Make kehta hai "already up-to-date" aur time bachata hai.
Har rule ke teen parts hote hain: target (jo banana hai), prerequisites (jis se banega), aur recipe (commands). Ek bahut common galti — recipe line TAB se start honi chahiye, spaces se nahi, warna missing separator error aata hai. Variables = (lazy, har baar expand) aur := (eager, ek hi baar value lock) se banate hain; derived lists ke liye := use karo taaki value stable rahe.
Sabse powerful cheez hai automatic variables: $@ = target, $< = pehla prerequisite, $^ = saare prerequisites. Inki wajah se aap ek hi generic pattern rule (%.o: %.c) likh ke saari .c files ke liye .o bana sakte ho — filename baar-baar likhne ki zarurat nahi. Yaad rakhne ka tarika: @=Aim (target), <=left wala (first), ^=poora hat (all). Ye toolchain ka backbone hai — bade C/C++ projects bina Make ke banana practically impossible hai.