makefile について
GNU Makeによるビルド自動化の作成と保守を解説するガイドです。Makefileを扱う開発者向けに、ルール、変数、レシピ、ターゲット、よく使われるパターンを説明します。
主な機能
- 01ルールと前提条件の構文
- 02変数代入と自動変数
- 03phonyターゲットと一般的なレシピ
- 04ビルド、品質確認、クリーンアップのパターン
- 05並列実行とレシピの注意点
活用シーン
- 01プロジェクト用のMakefile作成
- 02ビルド、テスト、lint、クリーンアップのターゲット追加
- 03レシピや変数の動作に関する問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ itechmeat/ llm-code --skill makefileインストール後、Claude Code で/makefileを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/functions.mdimplicit.mdpatterns.mdrecipes.mdsyntax.mdtargets.mdvariables.md詳細
Makefile スキル
GNU Make のビルド自動化を作成、保守するためのガイダンスです。
クイックナビゲーション
| トピック | リファレンス |
|---|---|
| ルール、前提条件、ターゲット | syntax.md |
| 変数の種類と代入 | variables.md |
| 組み込み関数 | functions.md |
| 特殊ターゲットと擬似ターゲット | targets.md |
| レシピの実行、並列処理 | recipes.md |
| 暗黙ルールとパターンルール | implicit.md |
| よく使う実用的なパターン | patterns.md |
基本概念
ルールの構造
target: prerequisites
recipe
重要: レシピの行は必ず TAB 文字で始める必要があります。
ファイルターゲットと擬似ターゲット
# 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/
変数の代入
| 演算子 | 名前 | 展開されるタイミング |
|---|---|---|
:= | 単純 | 定義時に一度 |
?= | 条件付き | まだ設定されていない場合 |
= | 再帰 | 使用のたび(遅延バインド) |
+= | 追加 | 既存の値に追加 |
CC := gcc # Immediate
CFLAGS ?= -O2 # Default, overridable
DEBUG = $(VERBOSE) # Late binding
CFLAGS += -Wall # Append
自動変数
| 変数 | 意味 |
|---|---|
$@ | ターゲット |
$< | 最初の前提条件 |
$^ | すべての前提条件(一意) |
$? | ターゲットより新しい前提条件 |
$* | パターンルールのステム |
基本パターン
ヘルプの自動生成
.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
プラットフォームの検出
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
OPEN := open
else ifeq ($(UNAME_S),Linux)
OPEN := xdg-open
endif
ビルドディレクトリ
BUILDDIR := build
SOURCES := $(wildcard src/*.c)
OBJECTS := $(patsubst src/%.c,$(BUILDDIR)/%.o,$(SOURCES))
$(BUILDDIR)/%.o: src/%.c | $(BUILDDIR)
$(CC) -c $< -o $@
$(BUILDDIR):
mkdir -p $@
環境変数のエクスポート
export PYTHONPATH := $(PWD)/src
export DATABASE_URL
test:
pytest tests/ # sees exported variables
よく使うターゲット
品質チェック
.PHONY: lint format check test
lint: ## Run linters
ruff check .
mypy src/
format: ## Format code
ruff format .
check: format lint test ## All quality checks
クリーンアップ
.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 との連携
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)
レシピの実行
各行は個別のシェルで実行
# 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
出力の抑制とエラー処理
target:
@echo "@ suppresses command echo"
-rm -f maybe.txt # - ignores errors
並列実行
make -j4 # 4 parallel jobs
make -j4 lint test # Run lint and test in parallel
出力の節度
入力 1 行につき、出力も 1 行にします。 echo の出しすぎは避けてください。
# ❌ 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"
条件分岐
DEBUG ?= 0
ifeq ($(DEBUG),1)
CFLAGS += -g -O0
else
CFLAGS += -O2
endif
ifdef CI
TEST_FLAGS := --ci
endif
ファイルのインクルード
# Required include (error if missing)
include config.mk
# Optional include (silent if missing)
-include local.mk
-include .env
よくある落とし穴
| 落とし穴 | 問題 | 解決策 |
|---|---|---|
| レシピ内のスペース | レシピには TAB が必要 | 実際の TAB 文字を使う |
| .PHONY の指定漏れ | test ファイルが存在すると make test が失敗する | .PHONY: test を宣言 |
| レシピ内の cd | 各行は新しいシェルで実行される | cd dir && command を使う |
= と := の混同 | 予期しない遅延展開が起きる | デフォルトで := を使う |
| エクスポートされていない変数 | サブプロセスから変数が見えない | export VAR |
| make 内の複雑なシェル処理 | 保守が難しい | 外部スクリプトに移す |
クイックリファレンス
# 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
リンク
関連項目
- patterns.md - 拡張パターンとレシピ
コメント
Markdown 対応