makeは、多くの場合、複数のソースファイルからなるプログラムのコンパイルに使われるのですが、もちろん単独のファイルのプログラムにとっても有用なユーティリティです。
例としてhello.cを扱ってみましょう。 ま、このコードなら
% gcc hello.c
ですむと言えばすむんですけどね。でも、実際は
% gcc -Wall -O2 -ascii -pedantic -g hello.c -lm -o hello
なぁ〜んて、沢山のオプションを付けたいときもあります。 特に-lmなんてつい忘れてしまいます(hello.cには不要だけど)。
さらにもうひとつ大きなメリット、makeを介してコンパイルすることにしておけば、emacsからのデバッグがとっても楽になります。 M-x compileでemacs内からコンパイルでき、もしエラーがあればC-x`をタイプすると自動的にエラーのあるファイルの該当行にカーソルが移動します。
make自身の使い方が難しかったりすると意味がないんですが、とっても簡単です。 プログラマはMakefileという名前のファイルにどのようにコンパイルするかの指示を書いておき、makeはそれを読んで依存関係に従ってコンパイルを実行します。 というわけで、このページは「Makefileの書き方の第一歩」なのです。
Makefileはコンパイルしたいファイルhello.cのあるディレクトリに置いてください。 この例の場合は、その内容は次の一行ですみます。 (gfortranの場合はFC=gfortranの一行も追加してください。 このページ内のコンパイラの指定、オプションの指定を参照。)
hello:
たったこれだけです。 このhelloは、「生成したい」実行ファイル名です。 生成したい対象のことを「ターゲット」と呼びます。 Makefileには、ターゲットは行頭からつめて書いてください。でないと動きません。
じゃ、makeを使ってみましょうか? hello.cとMakefileのあるディレクトリでmakeを実行します。 もしくは、hello.cを編集しているMule/EmacsのバッファでC-cC-cをタイプします。
$ ls
Makefile hello.c
$ make
cc hello.c -o hello
$ ls
Makefile hello.c hello
コンパイルされていますね。
この動作を追ってみましょう。makeコマンドは、
ここで、makeがccを使ってhello.cをコンパイルしたのは、makeが.cで終わるファイルはCのソースファイルだと知っていたからです。
さて、ここでもう一度makeを実行してみましょう。
$ make
make: `hello' is up to date.
up to date、つまり`hello'は最新であると言って何もコマンドを実行しません。 ターゲットである実行ファイルhelloはソースファイルhello.cから作られますが、helloを作った直後ですからhello.cに変更はなく、helloを作り直す必要はないとmakeが判断したのです。
makeはファイルのタイムスタンプ(ファイルの更新時刻)を再コンパイルの判断の基準にしています。 helloとhello.cのタイムスタンプを比較して、実行ファイルよりもソースファイルが新しければ再コンパイルの必要があると判断し、古ければ再コンパイルしなくてよいと判断するのです。
例えば、hello.cを保存しなおしてからmakeを実行すれば、論理的にはプログラムの変更がなくても再コンパイルされます。 また、touchコマンドを使えばタイムスタンプだけが変更できます。 これは意外と有用です。
$ touch hello.c
$ make
cc hello.c -o hello
「僕はgccを使いたいんだけど」というときにはMakefileに
CC = gcc
の一行を追加します。 C言語ではなくてFortranで、しかもgfortranを使いたいときは、
FC = gfortran
の一行を追加します。 「-Wallと-O2オプションを付けてコンパイルしたい」なら
CFLAGS = -Wall -O2
の一行の追加です。さらに「-lmなどのリンクオプションを付けたい」なら
LOADLIBES = -lm
を追加します。 これらはすべて、最初のターゲット(例ではhello:)より前に書きます。 以上の全てを追加したMakefileは次のようになります。
CC = gcc
CFLAGS = -Wall -O2
LOADLIBES = -lm
hello:
このMakefileを使ってmakeしてみましょう。
$ touch hello.c
$ make
gcc -Wall -O2 hello.c -lm -o hello
gccが使われてますし、指定したオプションがついていますね? リンカへのオプションもLDFLAGSで指定できます。
単独のファイルのコンパイルの時でも、makeの4文字でEmacsの中からならC-cC-cでコンパイルできるのはとっても楽だと思いませんか? なにせプログラミングにはデバッグ、つまり再コンパイルがつきものなんですから。 日にちを置いてからのコンパイルのときにもどんなオプションが必要だったから悩むこともなくなります。