30代エンジニアの備忘録のカバー画像

30代エンジニアの備忘録

組み込み開発・信号処理・プログラミングの技術メモと短編小説

Makefile入門|ビルド自動化の基本構文からパターンルールまで実践解説

シリーズ この記事は「コンパイル・リンク・ビルド(組み込み基礎)」の一部です。 シリーズ目次を見る

(2026年5月時点)Makefile は、ソースと生成物の 依存関係 と コマンド を書いたビルド用のファイルです(GNU Make が典型的)。CMake や Ninja と混同しないように:Make は「レシピ+ファイルの新しさ」でコマンドを走らせる道具、CMake は Makefile 等を生成するメタツールです。本記事は基本構文、変数、パターンルール、自動変数、.PHONY、小さいテンプレに絞ってメモしています。

make とは?

makeは、ファイル間の依存関係を解析し、更新が必要なファイルだけを再ビルドするツールです。ソースファイルが100個あるプロジェクトで1ファイルだけ変更した場合、makeは変更されたファイルとその影響範囲のみを再コンパイルします。 参考:GNU Make マニュアル

Makefileの依存関係グラフ
Makefileの依存関係グラフ

Makefile の基本構文とは?

Makefileは「ルール」の集合で構成されます。各ルールは、ターゲット(生成物)、依存関係(必要なファイル)、レシピ(実行するコマンド)の3要素で構成されます。

# Makefileの基本構文
ターゲット: 依存ファイル1 依存ファイル2
	レシピ(実行するコマンド)

# 具体例
myapp: main.o utils.o
	gcc main.o utils.o -o myapp

main.o: main.c main.h
	gcc -c main.c -o main.o

utils.o: utils.c utils.h
	gcc -c utils.c -o utils.o
💡
レシピの行頭は必ずタブ文字(スペースではない)です。スペースで代用するとエラーになります。エディタの設定に注意してください。

Makefile で変数を使う方法は?

Makefileでは変数を定義して、コンパイラやフラグを一元管理できます。変更時は CC/CFLAGS/SRCS など 1箇所の変数を直すだけで再ビルド条件が揃います。

# 変数定義
CC = gcc
CFLAGS = -Wall -Wextra -O2
LDFLAGS = -lm
SRCS = main.c utils.c math_lib.c
OBJS = $(SRCS:.c=.o)    # .c → .o に置換
TARGET = myapp

# ルール
$(TARGET): $(OBJS)
	$(CC) $(OBJS) $(LDFLAGS) -o $(TARGET)

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

clean:
	rm -f $(OBJS) $(TARGET)

自動変数($@ $< $^)とは?

make は、適用されているルールの文脈で展開される特殊変数があります(GNU Make で一般的)。

  • $@:そのルールのターゲット名(例:main.o)
  • $<:先頭の依存ファイル(例:main.c)
  • $^:依存ファイル一覧(重複は除く)
  • $?:ターゲットより新しい依存だけ

パターンルールの書き方は?

同じ変換パターンを個別に書く代わりに、%(ワイルドカード)を使って一般化できます。

# パターンルール: 任意の.cから.oへの変換ルール
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# これにより、main.c → main.o, utils.c → utils.o 等が
# 自動的にこのルールに従ってビルドされる
Makefileのビルドフロー
Makefileのビルドフロー

.PHONY ターゲットとは?

cleanのように実ファイルを生成しないターゲットは、.PHONYで宣言します。同名のファイルが存在した場合の誤動作を防ぎます。

.PHONY: clean all rebuild

clean:
	rm -f $(OBJS) $(TARGET)

all: $(TARGET)

rebuild: clean all

並列ビルドは make -j$(nproc) のようにすると試しやすいです。-j は「依存宣言が実際の生成物と一致している」ことが暗黙の契約で、欠けるとたまにだけ壊れた成果物や変な再ビルドが出ます(再現性のためには依存を先に整える)。規模が大きくなると CMake、Ninja などへ移る選択肢もあります。

実践的な Makefile テンプレート例は?

# 汎用的なC言語プロジェクト用Makefile
CC      = gcc
CFLAGS  = -Wall -Wextra -std=c11 -O2
LDFLAGS =
INCDIR  = include
SRCDIR  = src
OBJDIR  = obj

SRCS    = $(wildcard $(SRCDIR)/*.c)
OBJS    = $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SRCS))
TARGET  = myapp

.PHONY: all clean

all: $(TARGET)

$(TARGET): $(OBJS)
	$(CC) $(OBJS) $(LDFLAGS) -o $@

$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
	$(CC) $(CFLAGS) -I$(INCDIR) -c $< -o $@

$(OBJDIR):
	mkdir -p $(OBJDIR)

clean:
	rm -rf $(OBJDIR) $(TARGET)

まとめ:Make を使うときの要点は?

  • Make は「ファイルの新しさと依存」だけで実行するものを増やせるようにするツール
  • レシピ先頭は タブ。ここだけスペース禁止、が最初の転びポイントになりがちです
  • %.o: %.c と自動変数で重複記述を減らし、clean は .PHONY で明示