make とは
コマンド make とは、実行ファイルなどの作成を効率よく行なうためのソフトウェアです。コンパイルやリンクなどの手続きを記述した Makefile を用意すれば、この make コマンドが自動的に作業をしてくれます。また、一部のソースファイルに修正が生じた場合でも必要かつ最小限の作業で実行ファイルを再構築してくれるのです。
もちろんコマンド make は、実行ファイルを作成するためだけに使われるわけではありません。ターゲットとなるのはライブラリでも、PostScript ファイルでもよいのです。
make の使い方
さぁ、Makefile が作成できれば、最後はこのコマンド make の出番です。まずはコマンド make の使い方として、基本的かつ一般的なコンパイル、およびインストールの方法を知っておきましょう。
通常は以下のように makeコマンドを実行することで、ソースファイルのコンパイルが行なわれ、実行ファイルが作成されます。
$ make
たいていの Makefile は、これでターゲットである実行ファイルを作成されるように記述されています。
問題なく実行ファイルが作成されたならば、次に実行ファイルをインストールします。たいていは install という名前をターゲットにしていますので、以下のように makeコマンドを実行することになります。
$ make install
ただし、インストールするディレクトリは一般ユーザーの権限では書き込みができない場合があります。むしろ書き込み権限がないほうが普通です。書き込み権限が無ければ、この make install は、当然エラーとなります。その場合は root に、つまりスーパーユーザーになってから make install を行なう必要があります。
make install が成功すれば、たいていは必要なデータファイルや man や info などのマニュアルもインストールされます。
ただし xmkmf や imake で Makefile を作成した場合は、ほとんどの場合は以下のようにして man などのマニュアルを別途インストールする必要があります。
$ make install.man
便利なオプション
コマンド make にはいくつかのオプションがあります。通常のインストール作業でよく使用されると思われる makeコマンドのオプションを以下に挙げます。
- -f
- Makefile を指定します。
- -n
- コマンドを実行せずに表示のみ行ないます。
- -k
- コマンドがエラーを返しても、そのターゲットは放棄しますが、他のターゲットに関しては続行します。
- -i
- コマンドがエラーを返しても、それを無視します。
- macro=value
- マクロを定義します。
Makefile を指定
コマンド make は通常、"makefile" という名前のファイルを探し、それが存在していなければ "Makefile" という名前のファイルを探します。
(もし GNU Make を使用しているならば、"makefile" よりも、"GNUmakefile" というファイルが優先されます)
それ以外の名前のファイルを使用する場合は、makeコマンドのオプション "-f" を指定します。
例えば "winfile" というファイル名を Makefile に指定するには以下のように makeコマンドを実行します。
(「敗けファイル」は嫌、「勝ちファイル」がいいと、好んでこの名前にしている人を著者は少なくとも一人は知っています。:-))
$ make -f winfile
非実行
make コマンドのオプション "-n" はそのコマンド行を表示しますが、実行はしません。このオプションは、make を実行した場合どのような動作が行なわれるのかを事前に知りたい場合などに使用します。
例えば以下のファイルがカレントディレクトリにあるとします。
$ ls -l total 1 -rw-r--r-- 1 yokota users 18 Jul 4 22:14 Makefile
つまり "Makefile" だけです。このときの "Makefile" の内容は以下になっているとします。
file:
touch file
このときオプション "-n" を付けて makeコマンドを実行してみます。
$ make -n touch file $ ls -l total 1 -rw-r--r-- 1 yokota users 18 Jul 4 22:14 Makefile
つまり make コマンドは "touch file" というコマンド行を出力しますが、実行はしていません。この機能を使って、事前に makeコマンドの動作を確認することができます。オプション "-n" を指定せずに makeコマンドを実行した場合は当然以下のようになります。
$ make touch file $ ls -l total 1 -rw-r--r-- 1 yokota users 18 Jul 4 22:14 Makefile -rw-r--r-- 1 yokota users 0 Jul 4 22:19 file
ただし、この make コマンドのオプション "-n" には、いくつかの例外があります。
まず一つが、Makefile 内のコマンド行に "$(MAKE)" マクロの参照が含まれる場合は、そのコマンド行は必ず実行されることです。例として、以下のようなファイルがカレントディレクトリにあるとします。
$ ls -lt total 1 -rw-r--r-- 1 yokota users 84 Jul 4 17:16 Makefile -rw-r--r-- 1 yokota users 0 Jul 4 17:13 mfile.in -rw-r--r-- 1 yokota users 0 Jul 4 17:13 Target.in
このときの "Makefile" の内容は以下になっているとします。
all: Target
Target: Target.in
cd . && $(MAKE) mfile
mfile: mfile.in
touch mfile
このときオプション "-n" を付けて make コマンドを実行してみます。
$ make -n --no-print-directory cd . && make mfile touch mfile
つまり、"cd . && make mfile" というコマンド行が実際に実行されて、"touch mfile" というコマンド行の表示が行なわれています。ただし、もちろんこの "touch mfile" は表示だけで、実行はされていません。
なお、オプション "--no-print-directory" は、実行したディレクトリを表示しないように指示する、GNU make のオプションです。通常のインストール作業時にはディレクトリを表示してもらったほうが便利なのですが、ここでは説明をしやすくするためにこのオプションを与えてディレクトリの表示をしないようにして make コマンドを実行しています。
次に、Makefile 内のコマンド行の先頭に "+" が付いている場合です。例えば以下のファイルが存在しているとします。
$ ls -lt total 1 -rw-r--r-- 1 yokota users 46 Jul 4 17:40 Makefile -rw-r--r-- 1 yokota users 0 Jul 4 17:13 Target.in
このときの "Makefile" の内容は以下のようになっています。
all: Target
Target: Target.in
+touch Target
このときオプション "-n" を付けて make コマンドを実行してみます。
$ make -n touch Target $ ls -lt total 1 -rw-r--r-- 1 yokota users 0 Jul 4 17:40 Target -rw-r--r-- 1 yokota users 46 Jul 4 17:40 Makefile -rw-r--r-- 1 yokota users 0 Jul 4 17:13 Target.in
つまり、オプション "-n" を与えて make コマンドを実行したにもかかわらず "touch Target" というコマンド行が実際に実行されてしまっていることがわかります。この動作は GNU make の拡張機能です。
次に、Makefile 自身が更新の必要がある場合です。例えば以下のファイルが存在しているとします。
$ ls -lt total 1 -rw-r--r-- 1 yokota users 0 Jul 4 17:13 mfile.in -rw-r--r-- 1 yokota users 0 Jul 4 17:13 Target.in -rw-r--r-- 1 yokota users 75 Jul 4 17:11 mfile
ここで、"mfile" は Makefile であり、その内容は以下の通りです。
all: Target
Target: Target.in
touch Target
mfile: mfile.in
touch mfile
この Makefile を使用して、かつオプション "-n" を付けて make コマンドを実行してみます。
$ make -f mfile -n touch mfile touch Target $ ls -lt total 1 -rw-r--r-- 1 yokota users 75 Jul 4 17:15 mfile -rw-r--r-- 1 yokota users 0 Jul 4 17:13 mfile.in -rw-r--r-- 1 yokota users 0 Jul 4 17:13 Target.in
コマンド行の "touch mfile" が実行されてしまっていることが判りますでしょうか。make コマンドは Makefile の更新の必要があることを知ると、例えオプション "-n" が与えられていたとしても、それを無視して Makefile を更新するためにコマンド行を実行してしまいます。もちろん "touch Target" のほうはオプション "-n" が働いていますので実行はされません。この動作も GNU make の拡張機能です。
エラーを無視
通常 make は、実行したコマンドが 0 以外のエラーステイタスを返した場合、その場でエラー終了します。しかし、make コマンドのオプション "-k" は、そのターゲットの構築には失敗したものとみなして放棄しますが、その他のターゲットに関する作業は継続します。似たような動作をするものにオプション "-i" があります。オプション "-i" はコマンドのエラーを無視してそのまま継続します。この違いを以下の Makefile を使って解説します。
all: test1 test2
test1:
touch /test1/a
touch /test1/b
test2:
touch /test2/a
touch /test2/b
実行するシステムには /test1 も /test2 もなく、一般ユーザーで実行するため全てのコマンド行は必ず失敗してエラーステイタスを返します。
まず、オプションを与えずに make コマンドを実行してみます。
$ make touch /test1/a touch: /test1/a: No such file or directory make: *** [test1] Error 1
最初のコマンド行でエラーになってしまったため、make コマンドはその場で終了してしまいます。
次にオプション "-k" を与えて make コマンドを実行してみます。
$ make -k touch /test1/a touch: /test1/a: No such file or directory make: *** [test1] Error 1 touch /test2/a touch: /test2/a: No such file or directory make: *** [test2] Error 1 make: Target `all' not remade because of errors.
最初のコマンド行 "touch /test1/a" で失敗し、ターゲット test1 は放棄しますが、次のターゲット test2 のために "touch /test2/a" を実行していることが判ります。しかし、それもエラーを返すのでそこでターゲット test2 も放棄してしまいます。
次にオプション "-i" を与えて make コマンドを実行してみます。
$ make -i touch /test1/a touch: /test1/a: No such file or directory make: [test1] Error 1 (ignored) touch /test1/b touch: /test1/b: No such file or directory make: [test1] Error 1 (ignored) touch /test2/a touch: /test2/a: No such file or directory make: [test2] Error 1 (ignored) touch /test2/b touch: /test2/b: No such file or directory make: [test2] Error 1 (ignored)
最初の "touch /test1/a" でエラーになりますが、ターゲット test1 を放棄せず、そのエラーを無視して継続して "touch /test1/b" を実行しています。ターゲット test2 についても同様です。
マクロ定義
make コマンドの引き数で、Makefile で定義されているマクロに代わってマクロを定義することができます。例として以下の Makefile を使用します。
CC = cc
CFLAGS = -g
hello: hello.c
$(CC) $(CFLAGS) -o $@ $<
見ての通り、"hello.c" (もちろん Hello World です。:) というソースファイルをコンパイルし、"hello" という実行ファイルを作成する Makefile です。そしてカレントディレクトリに "hello.c" があるとして、まずはオプションを与えずに makeコマンドを実行します。
$ make cc -g -o hello hello.c
それに対し、次に "hello" を一度消去してから、make の引き数でマクロを定義して実行します。
$ make CC=gcc CFLAGS=-O gcc -O -o hello hello.c
上記の例ではマクロ "CC" を "gcc" に、"CFLAGS" を "-O" にして実行されていることが判ります。
二つ以上の単語を設定したい場合はシングルクォート('')かダブルクォート("")で囲む必要があることに注意してください。例として、"CFLAGS" に "-O2 -Wall" という値を設定したい場合は以下のように make コマンドを実行します。
$ make CC=gcc CFLAGS="-O2 -Wall" gcc -O2 -Wall -o hello hello.c
この引き数によるマクロ定義は make コマンドの実行によく使われれる方法です。