プログラムだけとは限りませんが、作業が複雑になるにつれ、 その分必要とする手間が増えます。 例えば、プログラムをコンパイルする環境が変われば、 コンパイラへ渡すオプションや参照するファイルの場所も変わります。 こう言った作業に伴う手間の縮小及び自動化を行うためのツールがmakeです。 makeは数多くのUNIX標準ツールとして用意されていますが、 今回は汎用性の高いGNU makeについて取り上げます。
操作 |
キー |
makeを実行する |
make |
代わりのファイルをMakefileとして使う |
make -f Sample.mk |
makeを実際実行せず、結果だけを提示する |
make -n all |
では、起動してみましょう。makeと打ち込んでみてください。ディレクトリ内にMakefileが無ければ、"Makefileがなく、何をmakeするべきか指定されていない"と表示されます。
$ make代わりにオプションとして-nを渡すと、実行されずに、その実行結果だけが表示されるはずです。
gmake: *** No targets specified and no makefile found. Stop.
$ make -nmakeコマンドは何も引数を渡さなければ、Makefileというファイルの中のallというエントリ内のコマンドを実行しようとします。他のファイルをMakefileの代わりに読み込む場合は-fオプションで読み込むファイルを指定します。
$ make -f Sample.mk clean
Makefile の中には、プログラムを作成する規則を書きます。規則は以下のように書きます。 コマンドの行は、行頭にタブ(Tab)が必要です。コマンドは1行ずつシェルへ渡されて実行されます。
ターゲット: 依存するファイル(複数あってよい) (Tabの後) コマンド
依存するファイルがターゲットよりも新しければ、コマンド行は1行ずつシェルへ渡されて 実行されます。 もし、helloworld.c が hello.h というファイルをインクルードしているとすると、 Makefileは以下のようになります。
helloworld: helloworld.o gcc -o helloworld helloworld.o helloworld.o: helloworld.c hello.h gcc -c helloworld.c
この Makefile には二つの規則が書かれています。まず、helloworldというファイルが
helloworld.o に依存していることを示し、helloworld.o が変更されたならば( helloworld
よりも変更された日付が新しいとき)、gccコマンドで helloworld を生成するというものです。
2つ目の規則は、helloworld.oが helloworld.c と hello.h に依存していて、いずれかが
変更されたときには gccコマンドで helloworld.o を生成するというものです。-c オプションは
拡張子が .o のオブジェクトファイルを生成することを意味します。
$ makeと入力すると、最新の helloworld が生成されます。
OBJECTS = helloworld.o gutentag.o helloworld: $(OBJECTS) gcc -o helloworld $(OBJECTS)変数を使うと繰り返しを避けることができます。
変数 | 意味 | デフォルト | CC | Cコンパイラ | cc | CFLAGS | Cコンパイラのフラグ |
|
LDFLAGS | リンカのフラグ |
|
CXX | C++コンパイラ | g++ | CXXFLAGS | C++コンパイラのフラグ |
|
CPP | Cプリプロセッサ | $(CC) -E | CPPFLAGS | Cプリプロセッサのフラグ |
|
$ make CFLAGS=0g helloworld暗黙の規則と変数は、次のように -p オプションを使って表示 することができます。
$ make -p
別の例で、実際につかってみましょう。まず以下のソースコードをダウンロードしてみましょう。
helloworld_gtk.cこのプログラムの中身は複雑になるので省きますが、前回書いたhelloworld.cというプログラムをポップアップ化したものです。コンパイルして実行すると画面に新しいウィンドウが現れ、「Hello World!」と表示されます。他に異なる点として、グラフィック関係の「ライブラリ」をリンクさせる必要があります。
ライブラリとはソフトウェアの一部を他ソフトウェアで再利用可能にするためのソフトウェアと言えます。この場合、0から新しくウィンドウを表示するためのグラフィックを書く手間を省くため、既存のグラフィックライブラリをこのプログラムへ含めます。また、ライブラリを利用することでソフトウェア間の互換性を保つこともできるため、今日のソフトウェアを開発する上では必要不可欠な要素であると言えます。
今回はgtkというグラフィックライブラリを使うことにします。 では、実際にどのように記述するかを説明します。
## コンパイラの指定一つずつ細かく見ていきます。
CC = gcc
## gccの最適化オプション
OPTIMIZE = -O2
## GLIB, GTKのバージョン
GDK_VER=1.2
GLIB_VER=1.2
GTK_VER=1.2
## コンパイラフラグ
CFLAGS = $(OPTIMIZE) -I. -I/usr/include/gtk-$(GTK_VER) -I/usr/include/glib-$(GLIB_VER) -I/usr/lib/glib/include
## コンパイルコマンド実行
## hello:hello.c の部分をプログラムのファイル名に合わせて変更
## 例: program.c ならば program:program.c に変更
all: helloworld_gtk
helloworld_gtk:helloworld_gtk.c
$(CC) $(CFLAGS) $@.c -o $@ -lgtk -lgdk -lglib
clean:
rm -f *.o
## コンパイラの指定
CC = gcc
## gccの最適化オプション
OPTIMIZE = -O2
## GLIB, GTKのバージョン
GDK_VER=1.2
GLIB_VER=1.2
GTK_VER=1.2
## コンパイラフラグ CFLAGS = $(OPTIMIZE) -I. -I/usr/include/gtk-$(GTK_VER) -I/usr/include/glib-$(GLIB_VER) -I/usr/lib/glib/include
makeでは独自の変数を宣言することができます。これにより、変数の値を状況に応じて変更することができます。この例ですと、CコンパイラとしてGNU ccを使い、最適化するように宣言を行います。また、グラフィックライブラリはバージョン1.2系列のものを使うようにしてしています。最後に、Cコンパイラ自身へのオプションとして、先程挙げた最適化を行い、さらに各種設定パラメータを含んだヘッダファイルを含めた検索すべきディレクトリを指定しています。
## コンパイルコマンド実行 all: helloworld_gtk helloworld_gtk:helloworld_gtk.c $(CC) $(CFLAGS) $@.c -o $@ -lgtk -lgdk -lglib
次に、コマンドの宣言を行います。makeはデフォルトでallというカテゴリで宣言されたコマンドを実行します。通常はmakeする場合は複数のプログラムを同時にコンパイルしますが、今回は一つだけですので「helloworld_gtk」と宣言します。
そのあとに、helloworld_gtkの中身を記述します。 コンパイラは上で宣言したCCとそのオプションを宣言し、ファイル名はこのカテゴリの名前、即ち「helloworld_gtk」.cを加えたものとなります。-oオプションはコンパイル後の実行ファイル名、この場合は「helloworld_gtk」と言う名前で生成します。最後に、リンクするべきライブラリを宣言します。今回はgtk, gdk, glibの三つを使います。
さて、実際makeしてみましょう。helloworld_gtk.cとMakefileのあるディレクトリでmakeを実行してみましょう。
$ make
helloworld_gtkという実行ファイルが生成されたはずです。最後に、これを実行してみましょう。
$ ./helloworld_gtk