makefile-best-practiceslisted
Install: claude install-skill air-gapped/skills
# Makefile Best Practices
**Target:** GNU Make 4.x. Covers Make as both a build system (dependency-driven
compilation) and a task runner (developer workflow automation).
## Golden Rules
### 0. Simplicity First
When creating Makefiles:
- Start with the minimum viable solution
- Each target should do ONE thing well
- If creating more than 10 targets or 100 lines, confirm scope with user first
- BUT: if user explicitly requests more targets, add them without pushback
### 1. Make is a Dependency Graph, Not a Script
Targets represent outputs; prerequisites represent inputs; recipes transform inputs → outputs. Think graph-first.
```makefile
# WRONG: Script thinking - order-dependent, breaks with -j
build:
compile src/a.c
compile src/b.c
link
# RIGHT: Graph thinking - declares real dependencies
program: a.o b.o
$(CC) -o $@ $^
%.o: %.c
$(CC) -c $< -o $@
```
### 2. Correctness Under `make -j` is the Real Bar
If it breaks with parallel builds, it's broken. Always declare real dependencies.
```makefile
# WRONG: Hidden dependency, races under -j
generated.h:
./generate-header.sh > $@
main.o: main.c # Missing: generated.h
$(CC) -c $< -o $@
# RIGHT: Explicit dependency
main.o: main.c generated.h
$(CC) -c $< -o $@
```
Validate dependency correctness with `make --shuffle=random -j` (GNU Make 4.4+).
Randomizing prerequisite order exposes missing edges that a fixed order hides.
### 3. Phony vs File Targets Drive Behavior
Use `.PHONY` for commands, not for artifacts. U