連載
» 2011年06月10日 00時00分 UPDATE

仕事で使える魔法のLAMP(9):Makefileをいろいろ書き換えながらビルドしてみよう

今回は、ビルド作業に必要な「make」というコマンドの使い方と、makeコマンドが実際にしている処理の内容を解説します(編集部)

[山口晴広,株式会社イメージズ・アンド・ワーズ]

暗黙のルールを理解する

 前回はmakeの簡単な使い方を説明しました。たった1行の設定ファイルを用意すれば、makeコマンドだけでビルドできるようになったわけですが、今回はその仕組みを明らかにしていきます。ただ、本連載の趣旨はソフトウェア開発ではありませんので、Makefileの書き方ということではなく、ビルドに必要なmakeの制御方法という側面から解説します。

 さて、まずは前回使用したMakefileをもう一度見てみましょう。

hello: main.o hello.o

 このコロンで区切る書式は、Makefileを書くときに最初に覚えてほしい基礎的なところです。コロンの前の部分をターゲットといいます。コロンの後の部分は、ターゲットを作るのに必要なファイルを示しています。この例では、最終的な実行形式ファイルであるhelloを作成するのに必要な、2つのオブジェクトファイルということになります。

 これ以上の情報は、Makefileにはまったくありません。本来であればコンパイラのコマンド名や、リンクやコンパイルのコマンドラインなどの情報が必要なはずです。それでも正しくビルドできるのは、あとの情報はすべてmakeにあらかじめ設定してあるからです。

 これを暗黙のルールといいます。ビルド手順の多くは、標準的なソフトウェアであれば、ほぼ共通です。それを毎回設定するのは無駄ですから、共通のルールを用意しておくことで、人間の手による設定を最小限にできるのです。もちろん必要があれば、暗黙のルールを上書きすることもできます。

Makefileの基本的な書式

 ターゲットの記述法は、正確には次のようになります。ターゲットはMakefile中にいくつでも記述できます。

ターゲット: 依存ファイル1 依存ファイル2 …
        コマンド1
        コマンド2
        …

 ターゲットよりも依存ファイルの方が新しければコマンドが実行されます。なお、コマンドの前の空白はスペースでなく、タブにしなければなりません。

 前回の例ではコマンドの行がありませんでしたが、これは暗黙のルールを利用して省略していたということになります。もし省略せずに記述するのであれば、次のようになります。

hello: main.o hello.o
        gcc hello.o main.o -o hello

 なお、もう1つ、暗黙のルールがあります。それはソースコードをコンパイルしてオブジェクトファイルを作るためのルールです。これは*.cを*.oへコンパイルするルールとしてmakeが自動的に処理します。

 makeが実行するターゲットは、makeコマンドの引数で指定します。省略した場合、Makefile中に最初にあらわれたターゲットを指定したことになります。この例ではhelloターゲットしかありませんので、「make」と実行した場合は「make hello」と同じ振る舞いになります。

 第6回や前回で、インストール時にはmake installと実行していたことを思い出してください。ここで出てくるinstallはターゲットだったわけです。しかし、make installを実行してもinstallというファイルが作成されるわけではありません。このように、ターゲットは実行したいコマンドを指示する目的でも使います。

 このような利用方法としてよくあるのは、ビルドした結果の消去です。Makefileに次の行を追加して、make cleanと実行してみましょう。

clean:
        rm -f *.o hello

 cleanターゲットには依存ファイルの指定がありません。このようにすると、ターゲットを指定したときは常にコマンドを実行するようになります。

 ターゲット名は自由でよいのですが、ターゲット省略またはallでビルドを実行、cleanでビルド結果の消去、installでインストール、というのが通例となっています。他にはtestまたはcheckで、ビルドしたソフトウェアのテストを実施するようになっていることもよくあります。このあたりの使い方は覚えておきましょう。

 ここまで使ってきたMakefileでは、ターゲットを省略したときは実行形式ファイルであるhelloとなっていました。これを通例に習って、allとするには次のようにします。

all: hello
hello: main.o hello.o

 makeの引数でターゲットを指定するときは、複数のターゲットを指定することもできます。その場合、ターゲットは指定した順に実行されます。make clean allとすれば、ビルド結果を消去してからビルドする、つまりビルドをやり直す、ということになります。

Makefileで使える変数

 makeを実行したときに表示されるコマンドラインでは、コンパイラがccになっていました。コンパイラのコマンド名なども、標準的な内容であらかじめmakeに設定されているのです。この設定はマクロと呼ぶ変数のようなものに格納します。

 マクロはMakefileの中で、次の書式で定義できます。

マクロ名=値

 マクロ名は大文字小文字を区別するので注意してください。=の前後は空白を入れても問題ありません。

 マクロについてもあらかじめ標準的なマクロ名や値がmakeに設定してあります。コンパイラを指定するマクロはCCです。Makefileを次のようにして、実行してみましょう。

CC = gcc
all: hello
hello: main.o hello.o

 コマンドがgccになったことが確認できるはずです。

 マクロの参照は、$(マクロ名)とします。helloターゲットのコマンドを省略せずに書くのであれば、次のようになります。

CC = gcc
all: hello
hello: main.o hello.o
        $(CC) hello.o main.o -o hello

 さらに、マクロはmake実行時に引数で上書きすることができます。上記のようなMakefileのとき、make CC=ccとすれば、gccではなくccでビルドが実行されます。

 マクロ名も自由でよいのですが、CCなどは暗黙のルールでも使われる標準的なマクロ名となっています。他にビルド時によく使うのは、コンパイラへのオプションを指定するCFLAGSや、リンク時のオプションを指定するLDFLAGSです。makeの実行時に変更したいものをマクロにしておくことで、柔軟にビルドできるようになっています。

 また、Makefileを簡潔に記述するためにも使われます。例えばオブジェクトファイル名をマクロにすることで、1つ前の例が次のようになります。

CC = gcc
OBJ = main.o hello.o
 
all: hello
hello: $(OBJ)
        $(CC) $(OBJ) -o hello

 2カ所にあらわれていたオブジェクトファイル名が1つにまとまり、オブジェクトファイルが増えたとしても、1カ所だけ修正すれば済むようになったことが分かると思います。

覚えておきたいほかの書式

 最後に、Makefileを読むために必要になる、そのほかの書式をざっと紹介します。

 まず、#ではじまる行はコメントです。

 ターゲットもマクロも、1行で記述しなければなりません。複数行に分割したい場合、次のように行末に「\」をおいて改行をエスケープします。

FOO = bar \
      baz

 これは「FOO = bar baz」と同じです。

 ターゲットでもマクロでもない命令行もあります。include命令は、その場所にほかのファイルを読み込みます。Apache HTTP Serverなど、大きなソフトウェアの場合、include命令を使って複数のMakefileで成り立っていることが多いのです。

 次回は実際のフリーソフトウェアを1つ取り上げて、ビルドをしてみます。

著者紹介

株式会社イメージズ・アンド・ワーズ
代表取締役
山口晴広(やまぐち はるひろ)



「仕事で使える魔法のLAMP」バックナンバー

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。