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).
**On the `dev` plugin.** Its members are grouped by "general development
tooling", not by a shared workflow — this skill has no dependency on
**`baml-expert`**, **`jinja-expert`**, or
**`transformers-config-tokenizers-expert`**, and none of them on it. Don't hunt
for a pipeline that isn't there. The one overlap worth knowing: a Makefile that
shells out to render templates is still a Makefile question here, but the
template body itself is `jinja-expert`.
## Golden Rules
### 0. Simplicity First
- Start with the minimum viable solution; each target does ONE thing well.
- Default to <=10 focused targets; expand only on explicit request.
### 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