あるディレクトリに、 sample1.c sample2.c sample3.c ... sample9.c と9個のソースファイルがあり、それぞれが単独で、実行可能なプログラムのソースだとします。 これらをmakeの一度の実行で作ることができます。 それぞれの実行ファイル名を sample1 sample2 sample3 ... sample9 とします。 そしてMakefileには
PROGS = sample1 sample2 sample3 sample4 sample5 \
sample6 sample7 sample8 sample9
all: $(PROGS)
と書いて make または make all を実行すればOKです。 allは$(PROGS)に依存するので、$(PROGS)が全て作られます。 各sampleXの生成は、makeが自動的にディレクトリ内にソースを探してコンパイルしてくれます。 もちろん、例えばsample7.cを変更して再makeするとsample7.cだけを再コンパイルします。
ところで、説明が後先になっていますが、
PROGS = sample1 sample2 sample3 sample4 sample5 \
sample6 sample7 sample8 sample9
は
PROGS = sample1 sample2 (途中省略) sample8 sample9
と書くのと同じです。 行末の'\'は継続行をあらわし、次の行の内容も続きですよという印です。 この'\'の前には一つ以上の空白が必要です。 これはソースだけでなく、コマンド部分にも利用できます
ここでsample3については別の生成方法を指定したい、例えば、sample3 以外はデフォルトのccを使い、sample3のみgccを使って-lmをつけたいとします。 そんなときは、allより後にそのターゲットを記述してやります。
PROGS = sample1 sample2 sample3 sample4 sample5 \
sample6 sample7 sample8 sample9
all: $(PROGS)
sample3: sample3.c
gcc sample3.c -lm -o sample3
のような具合です。 これで、やっぱり make または make all を実行すればOKです。
Makefileの書式は
ターゲット: ソース
コマンド
でした。 コマンドを省略できる場合があることは説明しましたが、ソースを省略することもできます。 つまり
ターゲット:
コマンド
です。 このとき、ターゲットの生成を指定すると、タイムスタンプを比較すべきソースがないので、必ずコマンドを実行します。
例を上げましょう。
CC = gcc
CFLAGS = -Wall -O2
OBJS = mycat.o getline.o copy.o
mycat: $(OBJS)
clean:
rm -f $(OBJS) *~ *.bak
2つ目のターゲットclean:に注目してください。 ソースがなくて、コマンドだけが記述されています。 引数なしでmakeを実行すると一つ目のターゲットmycat:を生成しようとしますが、
$ make clean
と引数にターゲットを指定することで2番目以降のターゲットを生成させることができます。 この例では
$ make clean
rm -f mycat.o getline.o copy.o *~ *.bak
となります。 これで、中間生成物であるオブジェクトファイルと編集時のバックアップファイルを消去できます。 これはフリーウェアについてくるMakefileでも良く見る書法です。