19
15

More than 3 years have passed since last update.

Makefileの基本

Last updated at Posted at 2020-06-26

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.aprog1 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コマンドの概要

19
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
15