Makefileの書き方

Makefileをなぜ書くのか

make(メイク)は、プログラムのビルド作業を自動化するツール。コンパイル、リンク、インストール等のルールを記述したテキストファイル (makefile) に従って、これらの作業を自動的に行う。

ja.wikipedia.org

つまり、コンパイルやリンクなどの一連の手順をMakefileに書いておけば、makeコマンドを実行するだけでコマンド実行などを自動的に行なってくれる。

Makefileの基本構造

Makefileに次のようなルールを書くことで、ビルド手順を指示する。

ターゲット : 前提条件
    コマンド
  • ターゲット:コマンドによって生成されるファイルの名称
  • 前提条件:ターゲットを生成するために必要なファイル
  • コマンド:makeが実行する動作

Makefileの例

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


ターゲット・前提条件・コマンドは複数指定することができる。

main: main.c sub.c
  gcc main.c sub.c -o main
注意

Makefileでは、コマンドの先頭はタブで始める必要がある。

スペースだとエラーが発生する。

$ make
Makefile:3: *** 分離記号を欠いています.  中止.

はてなブログの仕様により、タブがスペースに変換されるため、Makefileの例をコピペするとこのエラーが出るかもしれない。

コメント

Makefileでは、#から行末までの文字がコメントとして無視される。

# コメント
main : main.c # コメント
  gcc main.c -o main # コメント

変数

変数名 = 値で変数を定義し、$(変数名)で変数の値を使う。

# 変数定義
SRC = main.c

# 生成規則
main : $(SRC)
  gcc $(SRC) -o main

自動変数

Makefileでは、特別な意味を持つ変数(自動変数)がよく用いられる。

main : main.c
  gcc $^ -o $@  # gcc main.c -o main になる


自動変数一覧

変数名 意味
$@ ターゲットのファイル名
$% ターゲットメンバーの名前
$< 前提条件の一番最初の名前
$^ 前提条件の全ての名前
$? ターゲットよりも新しい全ての前提条件の名前
$+ 前提条件の全ての名前(重複があっても省略しない)
$* ターゲットのパターンマッチに一致した部分文字列


詳しい説明はこのサイトに書いてある。 quruli.ivory.ne.jp

擬似ターゲット

Makefileのターゲットには、実際にはファイルの名前でない擬似ターゲットを指定することができる。

clean:
  rm *.o

このように記述すると、make cleanと入力するとrm *.oコマンドが実行される。

ただし、cleanファイルが存在する場合、ターゲットは正しく機能しない。

$ make clean
make: 'clean' は更新済みです.

この問題を解決するために、cleanが擬似ターゲットであることを明示的に宣言する必要がある。

.PHONY: clean
clean:
  rm *.o