install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry-data
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/makefile" ~/.claude/skills/majiayu000-claude-skill-registry-data-makefile && rm -rf "$T"
manifest:
data/makefile/SKILL.mdsource content
Makefile Skill
Guidance for creating and maintaining GNU Make build automation.
Quick Navigation
| Topic | Reference |
|---|---|
| Rules, prerequisites, targets | syntax.md |
| Variable types and assignment | variables.md |
| Built-in functions | functions.md |
| Special and phony targets | targets.md |
| Recipe execution, parallel | recipes.md |
| Implicit and pattern rules | implicit.md |
| Common practical patterns | patterns.md |
Core Concepts
Rule Structure
target: prerequisites recipe
Critical: Recipe lines MUST start with TAB character.
File vs Phony Targets
# File target - creates/updates a file build/app.o: src/app.c $(CC) -c $< -o $@ # Phony target - action, not a file .PHONY: clean test install clean: rm -rf build/
Variable Assignment
| Operator | Name | When Expanded |
|---|---|---|
| Simple | Once, at definition |
| Conditional | If not already set |
| Recursive | Each use (late binding) |
| Append | Adds to existing value |
CC := gcc # Immediate CFLAGS ?= -O2 # Default, overridable DEBUG = $(VERBOSE) # Late binding CFLAGS += -Wall # Append
Automatic Variables
| Variable | Meaning |
|---|---|
| Target |
| First prerequisite |
| All prerequisites (unique) |
| Prerequisites newer than target |
| Stem in pattern rules |
Essential Patterns
Self-Documenting Help
.DEFAULT_GOAL := help help: ## Show available targets @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ awk 'BEGIN {FS = ":.*?## "}; {printf " %-15s %s\n", $$1, $$2}' install: ## Install dependencies uv sync test: ## Run tests uv run pytest
Platform Detection
UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Darwin) OPEN := open else ifeq ($(UNAME_S),Linux) OPEN := xdg-open endif
Build Directory
BUILDDIR := build SOURCES := $(wildcard src/*.c) OBJECTS := $(patsubst src/%.c,$(BUILDDIR)/%.o,$(SOURCES)) $(BUILDDIR)/%.o: src/%.c | $(BUILDDIR) $(CC) -c $< -o $@ $(BUILDDIR): mkdir -p $@
Environment Export
export PYTHONPATH := $(PWD)/src export DATABASE_URL test: pytest tests/ # sees exported variables
Common Targets
Quality Checks
.PHONY: lint format check test lint: ## Run linters ruff check . mypy src/ format: ## Format code ruff format . check: format lint test ## All quality checks
Cleanup
.PHONY: clean clean-all clean: ## Remove build artifacts rm -rf build/ dist/ *.egg-info find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true clean-all: clean ## Remove all generated files rm -rf .venv .pytest_cache .mypy_cache
Docker Integration
IMAGE := myapp VERSION := $(shell git describe --tags --always) docker-build: ## Build Docker image docker build -t $(IMAGE):$(VERSION) . docker-run: ## Run container docker run -d -p 8000:8000 $(IMAGE):$(VERSION)
Recipe Execution
Each Line = Separate Shell
# Won't work - cd lost between lines bad: cd subdir pwd # Still in original dir! # Correct - combine commands good: cd subdir && pwd # Or use line continuation also-good: cd subdir && \ pwd && \ make
Silent and Error Handling
target: @echo "@ suppresses command echo" -rm -f maybe.txt # - ignores errors
Parallel Execution
make -j4 # 4 parallel jobs make -j4 lint test # Run lint and test in parallel
Output Discipline
One line in, one line out. Avoid echo spam.
# ❌ Too chatty start: @echo "Starting services..." docker compose up -d @echo "Waiting..." @sleep 3 @echo "Done!" # ✅ Concise start: ## Start services @echo "Starting at http://localhost:8000 ..." @docker compose up -d @echo "Logs: docker compose logs -f"
Conditionals
DEBUG ?= 0 ifeq ($(DEBUG),1) CFLAGS += -g -O0 else CFLAGS += -O2 endif ifdef CI TEST_FLAGS := --ci endif
Including Files
# Required include (error if missing) include config.mk # Optional include (silent if missing) -include local.mk -include .env
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| Spaces in recipes | Recipes need TAB | Use actual TAB character |
| Missing .PHONY | fails if file exists | Declare |
| cd in recipes | Each line is new shell | Use |
vs confusion | Unexpected late expansion | Use by default |
| Unexported vars | Subprocesses don't see vars | |
| Complex shell in make | Hard to maintain | Move to external script |
Quick Reference
# Makefile Template .DEFAULT_GOAL := help SHELL := /bin/bash .SHELLFLAGS := -ec .PHONY: help install test lint format clean help: ## Show this help @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ awk 'BEGIN {FS = ":.*?## "}; {printf " %-15s %s\n", $$1, $$2}' install: ## Install dependencies uv sync --extra dev test: ## Run tests uv run pytest tests/ -v lint: ## Run linters uv run ruff check . format: ## Format code uv run ruff format . clean: ## Clean artifacts rm -rf build/ dist/ .pytest_cache
See Also
- GNU Make Manual
- patterns.md - Extended patterns and recipes