[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

2. イントロダクション

読者がmakeに何をさせるかを指示するためにmakefileと呼ばれる ファイルが必要であり、これがmakeに対してコンパイルやリンクの指示を するのです。

この章では、8つのC(言語)のソースファイルと3つのヘッダファイルからなる テキストエディタのプログラムのコンパイルとリンクを行なう簡単なmakefileについて 記述します。また、このmakefileではたとえばクリーンオペレーションを行なう種々の 命令の実行もmakeに指示します。より複雑なmakefileの例は、 複雑なmakefileの例.を参照してください。

makeによってエディタプログラムが再コンパイルされる際は、変更のある Cのソースファイルもコンパイルされなければならず、ヘッダファイルが 変更された場合にもそのヘッダを含むCのソースファイルは再コンパイル されなければなりません。また、それぞれのコンパイルによりソースに対応する オブジェクトファイルが作り出されます。最終的には、なんらかのソースファイルが 再コンパイルされた場合には、すべてのオブジェクトファイルは新たに作成されるか、 前回コンパイルされたかにかかわらず、新たな実行可能なエディタプログラムに リンクされなければならないのです。


[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

2.1 ルールとはどのようなものか

以下のようなルールを持つ、簡単なmakefileを見てください。

 
target … : prerequisitescommand
        …
        …

ターゲットは、通常はプログラムで生成される実行可能または オブジェクトファイルの名称ですが、‘clean’のように実行の動作を表わす こともあります(see section 偽のターゲット.)。

前提条件は、ターゲットを作成する際の入力として用いられ、 多くの場合いくつかのファイルからなっています。

コマンドは、makeが実行する動作で、あるルールを示す行には複数の 命令を記述することができます。 [Please Note:]コマンドラインの先頭はタブで始めなければなりません。 これは不注意を捉えるためですが、わかりにくいところでもあります。

通常、命令は前提条件のルールのなかに置かれ、この前提条件が変更になった場合でも ターゲットファイルを作成できます。しかし、ターゲットそのものに対する命令を 指定するルールの場合は、前提条件を必要としません。たとえば、ターゲットが ‘clean’のような削除命令を含むルールの場合には前提条件を持ちません。

また、1つのルールは、そのルールのターゲットであるファイルをどのように、 いつまたmakeするのかについて記述されていて、makeはターゲットを 作成または更新するための前提条件に基づいて命令を実行します。さらに、 ルールはそのほかの動作についても、どのように、また、いつの時点で動作するのかに ついても記述されています。See section ルールの記述.。

makefileはルール以外のテキストを含んでいる場合もありますが、簡単な makefileではルールだけを記述してあればよく、多少複雑に見える場合でも多かれ 少なかれテンプレートのパターンと同様です。


[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

2.2 簡単なMakefile

ここでは、実行可能なeditプログラムの簡単なmakefileを扱います。 このプログラムは8つのオブジェクトに依存し、さらにこのオブジェクトは 8つのCのソースと3つのヘッダから成り立っています。

この例では、すべてのCのソースは‘defs.h’を含み、editコマンドを 定義するソースだけは‘command.h’を含み、編集バッファを変更する低レベルの 部分のソースだけは‘buffer.h’の各ヘッダを含んでいます。

 
edit : main.o kbd.o command.o display.o \
       insert.o search.o files.o utils.o
        cc -o edit main.o kbd.o command.o display.o \
                   insert.o search.o files.o utils.o

main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
command.o : command.c defs.h command.h
        cc -c command.c
display.o : display.c defs.h buffer.h
        cc -c display.c
insert.o : insert.c defs.h buffer.h
        cc -c insert.c
search.o : search.c defs.h buffer.h
        cc -c search.c
files.o : files.c defs.h buffer.h command.h
        cc -c files.c
utils.o : utils.c defs.h
        cc -c utils.c
clean :
        rm edit main.o kbd.o command.o display.o \
           insert.o search.o files.o utils.o

長い行の場合は、バックスラッシュと改行によって2行にわたって記述することができ、 読みやすくすることができます。

このmakefileを使って‘edit’の実行ファイルを作ることができ、このためには キーボードから以下のように入力します。

 
make

また、このmakefileを使って実行可能なファイルとすべてのオブジェクトを そのディレクトリから削除する場合には、以下のように入力します。

 
make clean

このmakefileの例では、実行可能な‘edit’、オブジェクト‘main.o’と ‘kbd.oo’、さらにこれらに必要な‘main.c’と‘defs.h’が含まれ、 それぞれの‘.o’ファイルはターゲットでもあり、必須のものでもあります。 コマンドとしては‘cc -c main.c’と‘cc -c kbd.c’が含まれて います。

ターゲットがファイルである場合には、必須条件(となるファイル)になんらかの 変更があった際にはふたたびコンパイルされ、リンクされる必要があります。 さらにいかなる必要条件であっても自動的に生成されアップデートされる必要が あります。この‘edit’の例でも、8つのオブジェクトファイルに依存していて、 ‘main.o’はソースファイル‘main.c’とヘッダファイル‘defs.h’に 依存しています。

一方、シェルコマンドはターゲットと必要条件を含む行を辿っていき、 ターゲットとなるファイルをどのようにアップデートするかを示します。 また、makefile中のほかの命令とを区別するために、各行の先頭にはタブ文字が 置かれます。(覚えておかなければならないのは、make自身は各命令が どのように動作するかについてはまったく感知せず、ターゲットとなるファイルが 適切にアップデートされるための命令の使用はユーザーに任されるということです。 ターゲットとなるファイルがいつの時点でアップデートされなければならないか というルールに従って、すべてのmakeが実行されます。)

また、ターゲット‘clean’はファイルではなく動作の名前です。通常、ルールの なかではこれを実行することはないため、必要条件とはなりません。したがって、 明確に指示しない限り、makeは‘clean’の動作を行なうことはありません。 注意しなければならないのは、この‘clean’の動作は必要条件ではない だけではなく、ほかにいかなる必要条件も持たないことから、ルールの唯一の目的は、 指定された命令の実行であるということです。ファイルを参照せずに動作だけである ターゲットは、phony targets(偽のターゲット)と呼ばれます。このような ターゲットについては、See section 偽のターゲット.。makermなどの命令によるエラーをどのように無視するかといった事柄については、 See section コマンドのエラー.。


[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

2.3 makeはどのようにMakefileを処理するのか

デフォルトでは、makeは‘.’で始まる名前ではないターゲットから 開始され、これはdefault goal(デフォルトゴール)と呼ばれます。 デフォルトゴールがmakeが最終的に到達しようとするゴールとなります。 See section ゴールを指定する引数.。

前節の簡単な例では、デフォルトゴールは、実行可能な‘edit’ プログラムのアップデートでした。したがって、最初にそのルールを置くことに なります。

コマンドは以下のように実行します。

 
make

makeはカレントディレクトリにあるmakefileを読み出し、最初のルールを 実行して開始されます。この例では、‘edit’を再リンクすることですが、 makeはこのルールを実行するまえに‘edit’が依存するファイルに対する ルールを実行しなければなりません。それらの各ファイルはそれぞれのルールに 基づいて処理されます。すなわち、ソースファイルをコンパイルして‘.o’を アップデートします。再コンパイルは、オブジェクトファイルが存在しなかったり、 タイムスタンプが新しくなっている場合に必要条件であるソースファイルや ヘッダファイルに対して行なわれます。

ほかのルールは、そのターゲットがゴールの必要条件として出現する際に、 処理されます。仮にいくつかのほかのルールがゴールの依存対象となっていない 場合には、明確にmake cleanのようなコマンドを実行しない限り そのルールは処理されません。

オグジェクトの再コンパイルのまえに、makeは必要条件である ソースファイルとヘッダファイルのアップデートを考慮します。 ‘.c’や‘.h’ファイルがどのルールのターゲットでもないことや、 これらのファイルに対してmakefileでは何も動作を特定しないため、 makeはこれらのファイルに対して何も操作を行ないません。しかしながら、 BisonやYaccによって生成されたCプログラムについては、 それ自身のルールに従って自動的にアップデートしようとします。

必要とされるオブジェクトの再コンパイルのあと、makeは‘edit’と 再リンクするかどうかを決定します。この決定は‘edit’が存在しないか、 あるいはオブジェクトファイルがより新しいものである場合には必ず行なわれます。 もし、オブジェクトファイルが今まさに再コンパイルされたばかりで、 ‘edit’よりも新しいタイムスタンプである場合は‘edit’は 再リンクされます。

したがって、ファイル‘insert.c’に変更を加えたあと、makeを 実行した場合には、‘insert.o’をアップデートするためにコンパイルを行ない、 ‘edit’にリンクを行ないます。また、‘command.h’に変更を加えて makeを実行した場合には、オブジェクトファイル‘kbd.o’と ‘command.o’と‘files.o’をコンパイルによってアップデートし、 ‘edit’にリンクを行ないます。


[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

2.4 変数によるMakefileの簡素化

ここでの例では、‘edit’のルールにおいて、すべてのオブジェクトファイルを 2回リストする必要がありました。

 
edit : main.o kbd.o command.o display.o \
              insert.o search.o files.o utils.o
        cc -o edit main.o kbd.o command.o display.o \
                   insert.o search.o files.o utils.o

しかし、このような重複はまちがいのもとです。もし新しいオブジェクトが加えられた 場合に、一方に加えて他方は忘れてしまうかもしれません。そこで、変数を使うことに よってリスクを回避し、makefileを簡素化することが可能です。 Variablesは文字列を1度定義し、それ以後の複数の場所でこれに置き換える ものです(see section 変数の使用法.)。

標準的な方法では、makefileのほとんどはobjectsOBJECTSobjsOBJSobjあるいはOBJと名付けられた変数を 持ち、以下の例のように変数objectsをmakefileのなかに置きます。

 
objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

また、オブジェクトファイルのリストを置こうとするそれぞれの位置で ‘$(objects)’を書くことによって変数で代用することができます (see section 変数の使用法.)。

ここで、オブジェクトファイルに対する変数を使用した場合のシンプルな makefileのリストを示します。

 
objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
        cc -o edit $(objects)
main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
command.o : command.c defs.h command.h
        cc -c command.c
display.o : display.c defs.h buffer.h
        cc -c display.c
insert.o : insert.c defs.h buffer.h
        cc -c insert.c
search.o : search.c defs.h buffer.h
        cc -c search.c
files.o : files.c defs.h buffer.h command.h
        cc -c files.c
utils.o : utils.c defs.h
        cc -c utils.c
clean :
        rm edit $(objects)

[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

2.5 makeに命令を導き出させる

個々のCのソースファイルのコンパイルにおいては、makeは コンパイルの方法を理解できるため、いちいち命令を書く必要はありません。それは、 ‘cc -c’コマンドを使用して、‘.c’から‘.o’ファイルを アップデートする暗黙のルールに従っているのです。 たとえば、‘cc -c main.c -o main.o’コマンドによって、 ‘main.c’をコンパイルして‘main.o’を生成します。 したがって、オブジェクトファイルの生成に関してはルールから命令を省くことが できるのです。See section 暗黙のルールの使用.。

.c’ファイルがこのように自動的に使用される場合は、必要条件のリストに 自動的に追加されます。したがって、命令を省略する必要条件からも‘.c’ ファイルは除くことができます。

ここに上述のような変更と変数の用い方を示す例を示します。

 
objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
        cc -o edit $(objects)

main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h

.PHONY : clean
clean :
        -rm edit $(objects)

ここでは、実際のmakefileをどう記述するかを示していて、‘clean’は別に 記述されているものとします。また、偽のターゲット.と コマンドのエラー.を参照してください。

暗黙のルールについては便利なため重要といえます。そのため、 頻繁に目にすることになるでしょう。


[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

2.6 もう1つのMakefileのスタイル

makefileのオブジェクトが暗黙のルールだけで生成される場合は、makefileの別の スタイルが可能です。このスタイルでは、エントリーをターゲットではなく 必要条件でグルーピングすることができ、以下のようになります。

 
objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
        cc -o edit $(objects)

$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h

ここでは‘defs.h’はすべてのオブジェクトファイルの必要条件として 与えられています。また、‘commannnd.h’と‘buffer.h’は 具体的なオブジェクトファイルの必要条件となっています。

こちらのスタイルがよいかどうかは好みの問題で、コンパクトではあるものの、 個々のターゲットについてのすべての情報を1箇所にまとめるほうが わかりやすいことから、このスタイルを嫌う人もいます。


[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

2.7 ディレクトリをクリーンにするルール

プログラムをコンパイルすることは、それに対するルールを記述することだけでは ありません。makefileは、一般的に、プログラムのコンパイル以外のいくつかの 事柄を示します。たとえば、すべてのオブジェクトファイルや実行ファイルを 削除してディレクトリを‘clean’する方法などです。

ここにエディタプログラムのmakeにおけるクリーンのルールを どのように書いているかを示します。

 
clean:
        rm edit $(objects)

実際には、予期しない状況を処理するために多少複雑なルールを書く 必要があるかもしれませんが、以下のようにします。

 
.PHONY : clean
clean :
        -rm edit $(objects)

こうすることによって、rmによるエラーにも影響されず処理を継続し、 ‘clean’と呼ばれる現実のファイルによってmakeが混乱することを 防ぐことができます。 (偽のターゲット.、および コマンドのエラー.を参照。)

しかしながら、それがデフォルトの動作では困るため、makefileの先頭に 置くべきではありません。したがって、ここでの例のmakefileのように、 デフォルトのゴールをそのままにするために、エディタを再コンパイルする editのルールを先頭に置くようにします。

cleaneditの必要条件ではないので、何の引数も与えずに ‘make’を実行したとしても実行されることはありません。実行したい場合には ‘make clean’とタイプしなければなりません。 See section makeをどのように実行するか.。


[ << ] [ >> ]           [冒頭] [目次] [見出し] [ ? ]

この文書は新堂 安孝によって2009年9月22日texi2html 1.82を用いて生成されました。