makeコマンドを使ってみよう #1
基本的なコンパイル方法
C言語を学習しはじめて、最初に書くのは次のようなメッセージ表示が多いのではないでしょうか。
include <stdio.h>
int main(void)
{
printf("Hello!");
}
これをビルドするには、Linux環境では次のようにします。
$ gcc hello.c -o hello
すると、カレントディレクトリにhelloという実行ファイルが作成されます。
コンパイラgccにはいろいろな機能があります。例えば、最適化により実行を高速化する場合、次のように-O3というオプションを指定します。
$ gcc hello.c -o hello -O3
また、コンパイラによるチェックをすべて出力するには-Wallというオプションをしています。
$ gcc hello.c -o hello -O3 -Wall
さらに、プログラムをGDBを使って、デバッグできるようにするには、-gオプションを指定します。
$ gcc hello.c -o hello -O3 -Wall -g
というように、どんどんコマンドラインが長くなります。毎回、これを入力するのは大変ですね。
makeを使う
makeコマンドは、コマンドラインを自動的に入力してくれます。まず、一番最初のオプションがない例をmakeを使って実行してみます。
次のようなファイルを作成し、Makefileという名前をつけて保存します。また、このディレクトリには、先ほどのプログラムをhello.cという名前で配置しておきます。
hello: hello.c
gcc hello.c -o hello
先ほど、実行ファイルhelloを作成している場合、次のように削除しておきます。
$ rm -f hello
removed 'hello'
さて、いよいよ、makeを使ってみます。次のようにコマンドラインでmakeと入力してみてください。
$ make
gcc hello.c -o hello
makeと入力しただけで、Makefileで記述したコマンドが実行されました。つまり、makeコマンドを使うと、実際のコマンドラインの内容はどんなに長くて複雑でも、makeの4文字のみの入力で操作が完了します。
必要な時だけビルドしてくれる賢いツール
さて、もう一度makeと入力してみてください。
$ make
make: 'hello' is up to date.
今度は、helloはup to date (最新)だと表示されて、ビルドされませんね。プログラムのソースコードhello.cが変更されてないのでビルドする必要がないためです。
makeコマンドは、そのことをファイルのタイムスタンプから判断して、不要なビルドをスキップします。この例ではソースファイルは1つですが、大規模なプロジェクトでは数百、数千のソースファイルがあります。一方、そのようなプロジェクトでも、ビルド毎に修正されるソースファイルの数は、数個などの少ない場合が多いでしょう。ですので、すべてのソースファイルを毎回ビルドするのは、いたずらに時間と計算資源の浪費します。そのようなプロジェクトでは、make(または類似のソフトウェア)は必要不可欠なツールになっています。
それでは、hello.cを少し修正してみてください。例えば、メッセージの文字列を変えてもいいでしょう。あるいは、実際の内容を変えずに保存してタイムスタンプを更新してみてください。次のようにtouchコマンドを使えば、タイムスタンプだけが更新されます。そして、再度、makeと入力するとビルドが実行されるのが分かるでしょう。
$ touch hello.c
$ make
gcc hello.c -o hello
Makefileの書式の基本
先ほど記述したMakefileについて説明します。下の図のように一行目は、コロン(:)を挟んで左側に作成する実行ファイルの名前(hello)、右側にその作成に必要なソースファイル(hello.c)を記述します。左側のファイルをターゲットファイル、右側のファイルを依存ファイルと呼びます。2行目にはターゲットファイルを作成するコマンドを記述します。ターゲットファイルが存在しないか、そのタイムスタンプが依存ファイルのそれより古い場合、2行目に書いたコマンドが実行されます。
まとめ
今回は、makeコマンドの基本的な使い方を紹介しました。4月になって、新たにプログラミングを始める方もいると思います。プログラミング技術の向上には、試行錯誤しながら、何度もビルドすることが近道です。Makefileを使って効率的にビルドしてみてください。次回は、ソースファイルの構成が、もう少し複雑になった場合にどのように記述するか紹介します。