make (基本編)

make とは、依存関係を利用して作業を半自動化するものである。 作業手順を Makefile というファイルに記述しておくと、 「make」と入力するだけで作業を自動的に行なってくれる。 (Makefileの先頭は大文字でも小文字でもよいが、両方ある時には、Makefileのほうが makefileより優先される。)

基本中の基本

Makefile には、「ターゲット(作るもの)」「ソース(材料)」「実行コマンド(手順)」の3つを、次のように記述する。
「→」はTABを表しており、右矢印を書くのではない。

ターゲット:ソース1 ソース2 ソース3 ...
→コマンド1
→コマンド2
→コマンド3
   ...

このセットを「ルール」と呼ぶ。Makefileにはルールを複数書くことができる。

Makefile を書くときによくやる間違いには次のようなものがある。 正しく書いてあるように見えるのに動かない時にはチェックしよう。

「依存関係を利用して」とは

Makefileに書いた「ルール」は、 「もしソースが更新されていたら、ターゲットを作り直さなければならない。その方法は、これこれ」ということである。 逆にいえば、 「最新のソースに基づいてターゲットが既に作られていたならば、 ターゲットを作り直す必要はない」ということである。 このことを利用して、make は、ターゲットを作成するために 必要最小限の手順のみを行なう。

実際の例で見てみよう。 #はコメントの開始であり、#以降 行末までがコメントとなる。

# example of makefile
sample.dvi : sample.tex fig.eps
→platex sample.tex
→platex sample.tex
この例では、 sample.dvisample.texfig.epsに依存する。 sample.texfig.epsが最新の状態であり、 かつ、 sample.dviのほうがsample.texfig.epsよりも新しければ、 再度sample.dviを作りなおす必要はない。 そのため、「make」と入力しても platexコマンドの実行は行なわれない。 (なお、「変更されているかどうか」を本当に調べるのは大変なので, make コマンドは,単にソースとターゲットの最終更新時刻を 比較することで判断している。)

ひとつの Makefile に複数のルールを記述することができる。 単にmake とすると、一番 最初のルールのターゲットが対象となる。 2番目以降のルールを指定するには、 make ターゲット名のように引数で 指定する。 省略時に最初のルールが使われること以外は、 Makefile中での各ルールの前後関係に意味がない。

# makefile for pLaTeX2e

preview : sample.dvi
→xdvi sample.dvi &

sample.dvi : sample.tex fig.eps
→platex sample.tex
→platex sample.tex

clean :
→rm -f *.dvi *.aux *.log  *.tex~
この例では、ユーザが「make」とタイプすると次のようなことが起こる。
  1. ターゲットが省略されたので、一番上の preview がターゲットとなる。
  2. まず ソースである sample.dvi が最新の状態になっているかどうかを確認する。
  3. sample.dvi が最新かどうかは、「sample.dvi の作り方」すなわち 二番目のルールを使って確認する。
  4. 二番目のルールを見ると、「sample.tex と fig.epsより新しければよい」 と書いてある。 まず、sample.tex が最新かどうか確認する。sample.texを作るための ルールはないので、(sample.texが存在すれば) 無条件にsample.texは最新であると判断される。 同様に fig.eps をターゲットとするルールはないので、 (fig.epsが存在していれば)無条件に最新であると判断される。
  5. sample.tex と fig.eps が最新の状態であることが確認できたら、 依存関係をチェックする。
    • もし sample.dvi の更新日時が sample.tex よりも新しければ、 sample.dvi を作り直す必要はなく、最新の状態である。
    • もし sample.dvi の更新日時が sample.tex よりも古ければ、 sample.dvi を作り直さなければならないので、 platex sample.tex を2回実行する。 結果として sample.dvi が更新される。
    ここまでで、 sample.dvi が最新であることが保証される。2番目のルールの実行は終り。
  6. (1番目のルールに戻って) preview と sample.dvi の更新日時を比較する。 実はpreviewというファイルは存在しない。 存在しないファイルは「無限に古い」ものとして扱われる。 make は preview を作ろうとして、 「xdvi sample.dvi &」を実行し、その結果プレビュー画面が表示される。

preview, clean などは、 ルールに書かれた手順を実行しても生成されないので、 ダミーターゲットなど呼ぶ。 つまり、これらのルールに書かれている手順は、 毎回必ず実行されることに注意しよう。

マクロ定義の利用

Makefileの規模が大きくなってくると、 同じ文字列が何度も出てくることが多い。 このような場合には、マクロ定義を利用することによって、 集中管理することができるようになる。

マクロ定義は、「マクロ名 = 定義内容」のように宣言し、 利用する時には、 「$(マクロ名)」あるいは「${マクロ名}」 などと書く。

なお、特殊なマクロ名(自動変数と呼ばれる)として、 ターゲット名に展開される「$@」、 ソースに展開される「$^」などがある。
 
以下に、マクロ定義を利用した Makefileの例を示す。 このようにしておけば、 ファイル名がsample.tex から report.tex になったときでも、 最初の数行を書き換えるだけで済む。

# sample Makefile for tex

DVI    = sample.dvi
TEXSRC = sample.tex
FIGS   = fig1.eps fig2.eps

preview : $(DVI)
→xdvi $^ &

$(DVI) : $(TEXSRC) $(FIGS)
→platex $(TEXSRC)
# sample Makefile for C

CFLAGS = -g -Wall
LFLAGS = -lm -lX11
CC     = gcc $(CFLAGS)

runrun : runrun.c
→$(CC) -o $@ $(LFLAGS) $^