概要
- Makefile の基本構造と動作原理を分かりやすく解説
- C/C++ コンパイルを中心に、依存関係やビルドの仕組みを説明
- 変数・自動変数・ワイルドカード などの使い方を具体例で紹介
- cleanターゲット などの運用パターンや注意点もカバー
- GNU Make を前提にした説明で、実際に動かせるサンプル付き
Makefile入門ガイド
- Makefile は、大規模プログラムのどの部分を再コンパイルすべきかを決定するためのツール
- 主に C/C++ のビルドで利用されるが、他の用途や言語にも応用可能
- 依存関係グラフ を定義し、ファイルの更新状況に応じて必要な処理のみ実行
- Make の代替としては、SCons、CMake、Bazel、Ninjaなどが存在
- JavaやGo、Rustなど他言語にはそれぞれ独自のビルドツールがある
Makefileの基本構造
- ルール(rule) は「ターゲット: 依存ファイル コマンド」の形で記述
- コマンドは タブ文字 で始める必要あり(スペース不可)
- 依存ファイルが更新されていれば、ターゲットのコマンドが実行される
- ターゲット名と生成されるファイル名は一致することが多い
例:Hello World
- 最小のMakefile例
- hello: echo "Hello, World"
- make helloを実行すると、helloファイルがなければコマンドが実行される
例:Cプログラムのビルド
- blah.cファイル(内容:int main() { return 0; })を用意
- Makefile例
- blah: blah.c cc blah.c -o blah
- make実行時、blahがなければコンパイル
- blah.cを更新すれば再コンパイルされる
Makefileの本質
- 依存ファイルのタイムスタンプ を元に、再ビルドが必要か自動判定
- ファイルを改ざんし、タイムスタンプを古くすると、正しく検知できない場合もある
依存関係の連鎖例
- blah: blah.o cc blah.o -o blah
- blah.o: blah.c cc -c blah.c -o blah.o
- blah.c: echo "int main() { return 0; }" > blah.c
- 依存ファイルを削除・変更・touchすることで、どのターゲットが再実行されるか実験可能
常に実行されるルール
- 依存ファイルが生成されない場合、ターゲットは常に実行される
- 例
- some_file: other_file echo "This will always run, and runs second" touch some_file
- other_file: echo "This will always run, and runs first"
cleanターゲット
- clean はビルド成果物の削除用ターゲット
- デフォルトターゲットや依存関係に含まれないため、明示的にmake cleanで実行
- cleanファイルが存在すると実行されないため、.PHONY指定推奨
変数の利用
- 変数は := で定義(=も可)
- 例
- files := file1 file2
- some_file: $(files) echo "Look at this variable: " $(files) touch some_file
- 変数参照は$(変数名)または${変数名}
allターゲットと複数ターゲット
- デフォルトで複数ターゲットをビルドしたい場合、 all ターゲットを利用
- 例
- all: one two three
- one: touch one
- two: touch two
- three: touch three
ワイルドカードの使い方
- * はファイル名のマッチに利用、wildcard関数推奨
- 例:$(wildcard *.c)
- % はパターンマッチや置換に利用。ルール定義や特定関数で活躍
自動変数
- $@(ターゲット名)、$^(すべての依存ファイル)、$<(最初の依存ファイル)、$?(ターゲットより新しい依存ファイル)など
- 例
- hey: one two echo $@ echo $? echo $^ echo $< touch hey
暗黙ルール(implicit rules)
- CコンパイルなどはMakeの 暗黙ルール で自動的に処理される場合あり
- 暗黙ルールの利用は便利だが、混乱の元になることもあるため注意
このガイドを参考に、 Makefile の仕組みや記述方法を実際に手を動かしながら学習することを推奨