Makefileを書いてみる.1

基本文法?

Makefileの文法は以下の通り。

# Makefile
ターゲット: 依存ファイル1 依存ファイル2 依存ファイル3
	コマンド行1
	コマンド行2
	コマンド行3

ターゲットは作りたい「料理」、依存ファイルは必要な「材料」、コマンドは材料を変換する「レシピ」と考えればよさそう。また、"#"以降はコメントになる。

(例) hello.cから実行形式ファイルhelloをビルドしたい

まず以下のhello.cを作成。

/* hello.c */
#include <stdio.h>

int main() {
	printf("Hello World!\n");
	return 0;
}

hello.cと同じディレクトリに"Makefile"というファイルを作成。

# Makefile
hello: hello.c
	gcc -o hello hello.c

ターミナルでmakeを実行すると以下のようビルドしてくれる。

$ make
gcc -o hello hello.c

もう一度makeしてみると

$ make
make: `hello' は更新済みです

と表示される.つまりhello.cが更新されてるか確認して,必要なときだけビルドしてくれるみたい。

(例)hello.cとthank.cから実行形式ファイルhelloをビルドしたい

以下のようにhello.cとthank.cを作成する。

/* hello.c */
#include<stdio.h>
void thank(void);

int main(){
	thank();
	return 0;
}

/* thank.c */
#include<stdio.h>
void thank(void);

void thank(void){
	printf("Thank you!\n");
}

先ほどと同様にMakefileを作成する。

#Makefile
hello: hello.c thank.c
	gcc -o hello hello.c thank.c

これでmakeすると、問題なくhelloがビルドされる。しかし、hello.cを更新してmakeすると、更新していないthank.cも再度コンパイルされてしまい無駄。よって以下のようにMakefileを書く方が良いみたい。

#Makefile
hello: hello.o thank.o
	gcc -o hello hello.o thank.o
hello.o: hello.c
	gcc -c hello.c
thank.o: thank.c
	gcc -c thank.c

(例)hello.cからhelloを、sorry.cからsorryをビルドしたい

以下のようにhello.cとsorry.cを作成する。

/* hello.c */
#include<stdio.h>

int main(){
	printf("Hello World!\n");
	return 0;
}

/* thank.c */
#include<stdio.h>

int main(){
	printf("I'm sorry!\n");
	return 0;
}

次に、Makefileを作成する。

#Makefile
hello: hello.c
	gcc -o hello hello.c
sorry: sorry.c
	gcc -o sorry sorry.c

これでmakeすると、helloしかビルドできない。よって以下のようにする。

#Makefile
all: hello sorry
hello: hello.c
	gcc -o hello hello.c
sorry: sorry.c
	gcc -o sorry sorry.c

これで、makeを実行すると、

$ make
gcc -o hello hello.c
gcc -o sorry sorry.c

となり両方のファイルがビルドできる。ちなみに「make "ターゲット"」とすることでビルドするファイルを指定することができる。例えば、helloだけビルドしたい場合はmake helloを実行する。

中間ファイルを削除したい。 それと.PHONYって何?

ビルドするファイルが増えれば増えるほど、中間ファイルも増えてしまうので一括でそれらを削除できたら便利。よってMakefileに以下のように、cleanを加える。

# Makefile
ターゲット: 依存ファイル1 依存ファイル2 依存ファイル3
	コマンド行1
	コマンド行2
	コマンド行3
clean:
	rm -f 消去したいファイル

(例)ビルド後hello.oとsorry.oを消去したい

さっきの例でのビルド後にhello.oとsorry.oを削除するため、Makefileにcleanを追加。

#Makefile
all: hello sorry
hello: hello.c
	gcc -o hello hello.c
sorry: sorry.c
	gcc -o sorry sorry.c
clean:
	rm -f hello.o sorry.o

これでmake cleanを実行すると、hello.oとsorry.oが削除される。

ターゲットにcleanを指定しているが、cleanという名前のファイルを作るよう操作しているわけではない点に注意。こういったターゲットを"phony target"というらしい。(さっきの例のallもphony target。)

(例)ディレクトリにphony targetと同じ名前のファイルがあると困る

cleanというファイルを作ってからmake cleanを実行してみる。

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

となりmake cleanが実行できない。解決策として、以下のようにMakefileのcleanの上に".PHONY"と追記する(allも同様なので追記しとく)。

#Makefile
.PHONY: all
all: hello sorry
hello: hello.c
	gcc -o hello hello.c
sorry: sorry.c
	gcc -o sorry sorry.c
.PHONY: clean
clean:
	rm -f hello.o sorry.o

これでmake cleanが実行できるようになる。