About make
A GNU Make skill for agents writing and troubleshooting Makefiles in C/C++ projects. It covers dependency tracking, pattern rules, build configurations, and organizing multi-directory projects.
Key features
- 01Core C/C++ Makefile patterns
- 02Automatic dependency generation and tracking
- 03Pattern rules and automatic variables
- 04Debug and release build configuration
- 05Parallel builds and installation rules
- 06Multi-directory project organization
Use cases
- 01Writing a Makefile for a C project
- 02Fixing rebuilds after header changes
- 03Diagnosing repeated builds or rule errors
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill makeAfter installing, type/makein Claude Code to confirm it loaded.
Bundled filesreferences/cheatsheet.md
Details
From the project READMEGNU Make
Purpose
Guide agents through idiomatic Makefile patterns for C/C++ projects: phony targets, pattern rules, automatic dependency generation, and common build idioms.
Triggers
- "How do I write a Makefile for my C project?"
- "My Makefile rebuilds everything every time"
- "How do I add dependency tracking to Make?"
- "What does
$@,$<,$^mean?" - "I'm getting 'make: Nothing to be done for all'"
- "How do I convert my shell compile script to a Makefile?"
Workflow
1. Minimal correct Makefile for C
CC := gcc
CFLAGS := -std=c11 -Wall -Wextra -g -O2
LDFLAGS :=
LDLIBS :=
SRCS := $(wildcard src/*.c)
OBJS := $(SRCS:src/%.c=build/%.o)
TARGET := build/prog
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
build/%.o: src/%.c | build
$(CC) $(CFLAGS) -c -o $@ $<
build:
mkdir -p build
clean:
rm -rf build
Automatic variables:
$@— target name$<— first prerequisite$^— all prerequisites (deduplicated)$*— stem (the%part in a pattern rule)$(@D)— directory part of$@
2. Automatic dependency generation
Without this, changing a header doesn't trigger a rebuild of .c files that include it.
CC := gcc
CFLAGS := -std=c11 -Wall -Wextra -g -O2
DEPFLAGS = -MMD -MP # -MMD: generate .d file; -MP: phony targets for headers
SRCS := $(wildcard src/*.c)
OBJS := $(SRCS:src/%.c=build/%.o)
DEPS := $(OBJS:.o=.d)
TARGET := build/prog
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
build/%.o: src/%.c | build
$(CC) $(CFLAGS) $(DEPFLAGS) -MF $(@:.o=.d) -c -o $@ $<
-include $(DEPS) # '-' ignores errors on first build (no .d files yet)
build:
mkdir -p build
clean:
rm -rf build
3. Pattern rules cheatsheet
# Compile C
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
# Compile C++
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
# Generate assembly
%.s: %.c
$(CC) $(CFLAGS) -S -o $@ $<
# Run a tool on each file
build/%.processed: src/%.raw | build
mytool $< > $@
4. Common Make patterns
Debug and release builds
BUILD ?= release
ifeq ($(BUILD),debug)
CFLAGS += -g -Og -DDEBUG
else
CFLAGS += -O2 -DNDEBUG
endif
Usage: make BUILD=debug
Parallel builds
make -j$(nproc) # use all CPUs
make -j4 # exactly 4 jobs
Add -Otarget (or -O) for ordered output: make -j$(nproc) -O
Verbose output
# In Makefile: suppress with @
build/%.o: src/%.c | build
@echo " CC $<"
@$(CC) $(CFLAGS) -c -o $@ $<
Override silence: make V=1 if you guard with $(V):
Q := $(if $(V),,@)
build/%.o: src/%.c
$(Q)$(CC) $(CFLAGS) -c -o $@ $<
Installing
PREFIX ?= /usr/local
install: $(TARGET)
install -d $(DESTDIR)$(PREFIX)/bin
install -m 0755 $(TARGET) $(DESTDIR)$(PREFIX)/bin/
5. Multi-directory projects
For medium projects, avoid recursive make (fragile, slow). Use a flat Makefile that includes sub-makefiles:
# project/Makefile
include lib/module.mk
include src/app.mk
# lib/module.mk
LIB_SRCS := $(wildcard lib/*.c)
LIB_OBJS := $(LIB_SRCS:lib/%.c=build/lib_%.o)
OBJS += $(LIB_OBJS)
build/lib_%.o: lib/%.c
$(CC) $(CFLAGS) -c -o $@ $<
6. Common errors
| Error | Cause | Fix |
|---|---|---|
No rule to make target 'foo.o' | Missing source or rule | Check source path and pattern rule |
Nothing to be done for 'all' | Targets up to date | Touch a source file or run make clean |
Circular dependency dropped | Target depends on itself | Check dependency chain |
missing separator | Tab vs spaces | Recipes must use a tab, not spaces |
*** multiple target patterns | Pattern rule syntax error | Check % placement |
| Rebuilds everything every time | Timestamps wrong, or PHONY missing | Check date; ensure all is .PHONY |
| Header change not detected | No dep tracking | Add -MMD -MP and -include $(DEPS) |
For a full variable and function reference, see references/cheatsheet.md.
Related skills
- Use
skills/build-systems/cmakefor CMake-based projects - Use
skills/build-systems/ninjafor Ninja as a make backend - Use
skills/compilers/gccfor CFLAGS details