TL;DR
Makefileについてうろ覚えだったので、調べてみました。
間違い等ありましたら、コメントいただけると幸いです。
Makefileとは
プログラム開発だけでなく、いろいろな作業を自動化してくれる便利なファイルです。
Makefileはシェルコマンドで実行できるどんな言語でも記述できます。
基本的には、
$ make
これだけで、Makefileに記載されたコマンドが走ります。
基本
ファイル名:
[ファイル作成のためのコマンド行]
これがmakefileの基本形になります。このかたまりをルールと呼びます。
Makefileには、複数のルールを含めることができます。
ルールの中にある [ファイル名] のことをターゲットと呼びます。
ターゲットは通常、プログラムによって生成されたファイルの名前です。
clean
のように実行するアクションの名前でもOKです。
[ファイル作成のためのコマンド行] は複数行書いてOKです。
※[ファイル作成のためのコマンド行] の手前には、タブ1文字を入れること!
長いラインはバックスラッシュ\
と改行を続けて書いて2行に分割します。
複数のルールを書いた場合
複数のルールを書いた場合には、make
を実行するときにターゲット名を指定するようにします。
指定しなかった場合は、一番最初に書かれたルールが実行されます。
$ make target
さらに、複数のターゲットを同時にmake
したい場合は、以下のように書きます。
$ make target1 target2
依存関係
依存ターゲットとは、そのターゲットを作るために必要なターゲットのことです。
target1というターゲットを作るためにtarget2という部品が必要な場合、以下のように書きます。
target1: target2
[target1のコマンド行]
make実行時に依存ターゲットがあれば、ターゲットの更新日時を比較してコマンド行を実行すべきかどうか判断します。
例えば、
target1:target2
[target1のコマンド行]
target2:
[target2のコマンド行]
というMakefileで
$ make target1
を実行すると、
まず、依存ターゲットtarget2を作成(=[target2のコマンド行]を実行)します。
※ただし、次の条件が成り立つときは何もしません.
・依存ターゲットファイルがすでに存在している場合
次に、target1を作成(=[target1のコマンド行]を実行)します。
ただし、次の条件が成り立つときは何もしません。
・target1とtarget2という名前のファイルが存在しており、target1の更新日付がtarget2の更新日付より新しい場合
もし更新日時が依存ターゲットより新しいならば、makeは何しません
複数のターゲットをまとめる
target1 target2: target3
[コマンド行]
と書いた場合、次の2つのルールがあるのと同じです。
target1: target3
[コマンド行]
target2: target3
[コマンド行]
.PHONY フォニーターゲット
ファイル名ではないターゲット(実行時のアクションをターゲット名にできる)をフォニーターゲット(Phony target=偽のターゲット)といい、明示的にコマンドを実行させたい時にこの名前を利用します。
フォニーターゲットを使うのには、同名のファイルとの衝突の回避、パフォーマンスの向上という二つの理由があります。
以下のように書きます。
.PHONY clean
clean:
rm *.o temp
.PHONY
の行は、それに続くターゲットがフォニーターゲットであることを明示的に表しています。
一応、書かなくても動きますが、万が一、同名のファイル(ここではclean
)ができたときに、ストップしてしまうことを防ぎます。
例
以下、Makefileの例になります。
make
または make mylib.a
で prog1
prog2
prog3
を実行します。(依存ターゲット)
また、make clean
で全ての .o ファイルを削除します。
変数は $(変数名)
で呼び出します。
$@
:ターゲットに同じ
$<
:依存ターゲットに同じ
CC = gcc
CFLAGS = -c -Wall -Wextra -Werror
LIBS = ar -rc
SOURCES = putchar.c swap.c
OBJS = putchar.o swap.o
TARGET = libme.a
$(TARGET): $(OBJS)
$(LIBS) $(TARGET) $<
$(OBJS): $(SOURCES)
$(CC) $(CFLAGS) -o $@ $<
.PHONY: clean
clean:
rm -f $(OBJS)
以上です。 こんな感じで、ライブラリの更新など自動化していきましょう。
ではでは。
参考資料
もっと詳しく知りたい方はこちらをご覧ください。
・make触ってみた
・自動化のためのGNU Make入門講座 - Makefileの基本:ルール
・GNU make 日本語訳(Coop編) - makeコマンドの概要