makeコマンドとMakefile

makeは、ソースファイルの依存関係を定義して、コンパイルの必要のあるソースファイルだけをコンパイルするためのツールです。Makefileと呼ばれる設定ファイルを記述します。makeには、nmakeやdmakeやcmakeなどの方言がありますが、ここで紹介するmakeはGNU makeです。

makeをなぜ使うのか?

makeをなぜ使うのかという動機について書きます。

C言語のソースファイルのコンパイルを待つのが辛い

makeを記述する一番の動機は、C言語のソースファイルが増え、記述量も増えてくると、C言語のソースファイルのコンパイルを待つのが辛いということです。

C言語のパフォーマンスを最大にするために「-O3」オプションをgccに与えることが多いと思います。これは、ソースファイルが大きくなってくるとコンパイルに非常に時間がかかります。

修正したファイルに依存しているものだけが、再コンパイルされると、時間の短縮になります。

UNIX/Linuxにおける一般的なインストール手順

UNIX/Linuxにおける一般的なソフトウェアのインストール手順は、次のように定型化されています。「./configure」などのコマンドで、OSの設定を調べて、Makefileを生成します。生成されたMakefileをmakeで実行して、コンパイルを行い「make install」で、ソフトウェアを配置します。

./configure
make
make install

Makefileの基礎

ここではMakefileの基本的なことだけを解説します。分割コンパイルで解説したアプリケーションの実行ファイルを生成するためのMakefileを書いてみます。「make」でアプリケーションの実行ファイルを生成、「make clean」で、途中できるオブジェクトファイルと実行ファイルを削除します。

以下が、Makefileの中身です。「all」の記述は「make」の動作を記述します。「clean」の記述で「make clean」の動作を記述します。先頭がタブになっている部分は、実行したいコマンドです。「::」の後ろは、依存しているファイル(あるいは単なるシンボル)を記述します。二行目以降は、タブで始め(空白ではない)、実行したいコマンドを記述します。

依存関係は連続して記述でき、依存先のファイルに更新があった場合は、コマンドが実行されます。

分割コンパイルで解説したファイルに対してMakefileを記述してみます。「make」コマンドで分割コンパイルとリンクをして実行ファイルを生成します。「make clean」で、生成されたオブジェクトファイルと実行ファイルを削除します。

all :: myapp

myapp : myapp.o mylib1.o mylib2.o
	gcc -o myapp myapp.o mylib1.o mylib2.o

myapp.o :: src/myapp.c
	gcc -Iinclude -c -o myapp.o src/myapp.c

mylib1.o :: src/mylib1.c include/mylib1.h
	gcc -Iinclude -c -o mylib1.o src/mylib1.c

mylib2.o :: src/mylib2.c include/mylib2.h
	gcc -Iinclude -c -o mylib2.o src/mylib2.c

clean ::
	rm *.o
	rm -f myapp

makeを実行してみましょう。

$ make
gcc -Iinclude -c -o myapp.o src/myapp.c
gcc -Iinclude -c -o mylib1.o src/mylib1.c
gcc -Iinclude -c -o mylib2.o src/mylib2.c
gcc -o myapp myapp.o mylib1.o mylib2.o

実行ファイル「myapp」が生成されます。試しに「src/mylib1.c」だけを修正してみましょう。makeを実行すると必要なコマンドだけが実行されます。

$ make
gcc -Iinclude -c -o mylib1.o src/mylib1.c
gcc -o myapp myapp.o mylib1.o mylib2.o

「make clean」を実行しましょう。オブジェクトファイルと、実行ファイルが削除されます。

$ make clean
rm *.o
rm -f myapp

makeは依存しているファイルの更新があったことをどのように検知しますか?

たとえば「mylib.c」は「mylib1.h」に依存しているとします。この場合は「mylib.c」の更新時刻よりも「mybli1.h」の更新時刻が新しかった場合に、ファイルの更新があったと判断します。

Makefileの生成を自動化したい

Makefileはテキストファイルですので、Linux/UNIXにおける実用的なテキスト処理プログラミング言語であるPerlで生成するのも簡単です。Makefileはmakeの種類によって方言があるので、Perlの側で吸収してあげるという使い方も可能です。

Windowsでもmakeは使えるの?

WindowsでMinGWを使う場合は、makeコマンドではなく「gmake」コマンドを使用します。Makefileの記述は、紹介したものと同じです。Windowsの場合は、makeは「nmake」を意味しており、衝突が起こるために、gmakeになっていると考えられます。

関連情報