Makefile実践——変数・パターンルール
前回のMakefile基本では、決め打ちのターゲットを並べるだけでした。しかし複数のソースファイルを扱う実際のプロジェクトでは、それでは行が増えるばかりで破綻します。ここでは変数・自動変数・パターンルール・.PHONYを使い、ファイルが増えても書き換えずに済むMakefileの作り方を学びます。あわせて、ヘッダを直したときにきちんと再ビルドされる依存関係の考え方も押さえます。少し複雑に見えますが、型さえ覚えれば一生使い回せる書き方です。
前回のMakefileは、ターゲットと材料をひとつずつ手書きした。ファイルが2つ3つのうちはそれでよいが、10個・20個になると同じような行を延々コピーする羽目になり、書き間違いも増える。
🧮 変数でコンパイラとオプションをまとめる
Makefileの中でも CC = gcc のように書けば、CC という変数にgccという値を代入できる。以降 $(CC) と書けば、その場所にgccが展開される。CFLAGS = -Wall -g のようにコンパイルオプションも同じ形で変数化できる。
app: main.o $(CC) $(CFLAGS) -o app main.o のように書いておけば、コンパイラやオプションを変えたいときはMakefile先頭の2行を書き換えるだけで済む。変数を使っていなければ、全ターゲットのgccという文字列を1つずつ探して直すことになる。
代入には = と := の2種類があり、= は使われる瞬間に右辺を評価する遅延代入、:= はその場で即座に評価する即時代入だ。予測しやすくしたいときは := を既定にしておくと事故が少ない。
🎯 自動変数——$@ $< $^ の三兄弟
ルールの右辺でターゲット名やファイル名を何度も書き写すのは面倒でコピペミスの元にもなる。Makeにはこれを自動で埋めてくれる自動変数がある。
$@ はそのルールのターゲット名、$< は最初の依存ファイル、$^ は依存ファイルすべてを空白区切りで並べたものに展開される。この3つ(cba-automatic-var)を覚えるだけで、ルールが一気に短く書ける。
迷ったら、ターゲット名は $@、材料全部は $^、最初の1個だけなら $< と覚えると使い分けやすい。
🔁 パターンルールで.cを一気に.oへ
自動変数と組み合わせて真価を発揮するのがパターンルール(cba-pattern-rule)だ。%.o: %.c と書けば「.cから同名の.oを作る」というルールを1つで表現できる。
🏷️ .PHONYで「ファイルではない」と教える
clean や all は、実際のファイルを作るためではなく単なる操作名として使うことが多い。ところが同じ名前のファイルがたまたま存在すると、makeは「もう最新だから何もしない」と誤解してしまう。
この事故を防ぐのが .PHONY だ。.PHONY: clean all のように宣言しておくと、clean や all は実在ファイルと関係のない「常に実行される名前」として扱われる(cba-phony-target)。
付け忘れても多くは問題なく動くが、同名ファイルが紛れ込んだ瞬間に「なぜか実行されない」という分かりにくいバグになる。clean・allなど操作系には習慣として付けておくとよい。
🔗 依存関係——ヘッダを直したら再ビルドされるように
ここまでは.cファイルだけを見てきたが、実際には.hヘッダファイルも変更する。困るのは、ヘッダだけを直してmakeを実行しても、対応する.oが古いままだと見なされず再コンパイルされないケースだ。
原因は単純で、Makefileのルールに書いた依存が main.o: main.c のように.cしか含んでいないからだ。makeは書かれた依存しか見ないため、ヘッダが変わったことに気づけない。
🧱 小さなプロジェクトの雛形
ここまでの要素を合わせると、複数の.cファイルと共通ヘッダを持つ小さなプロジェクトのMakefileは、次のような形にまとまる。
この形を手元に置いておけば、ファイルが増えても OBJS の行に名前を足すだけでよい。次は、生み出したオブジェクトファイルを他のプログラムからも使えるライブラリという形にまとめる方法に進む。