## 3 Makefileの書き方

システムを再コンパイルする方法を`make`に伝える情報は、*makefile*というデータベースを読み込むことで得られます。

### 3.1 Makefileに含まれるもの

makefileには、*明示的なルール*、*暗黙のルール*、*変数の定義*、*ディレクティブ*、*コメント*という5種類の要素が含まれます。ルール、変数、ディレクティブについては、後の章で詳しく説明します。

- *明示的なルール*は、そのルールの*ターゲット*と呼ばれる1つ以上のファイルを、いつ、どのように作り直すかを指定します。ターゲットが依存するほかのファイルを、ターゲットの*前提条件*として列挙し、ターゲットを作成または更新するためのレシピも指定できます。{{0|ルールの書き方}}を参照してください。

- *暗黙のルール*は、ファイルの名前に基づいて、ある種類のファイルをいつ、どのように作り直すかを指定します。ターゲットが、それと似た名前のファイルにどのように依存するかを記述し、そのターゲットを作成または更新するレシピを指定します。{{0|暗黙のルールの使用}}を参照してください。

- *変数の定義*は、後でテキスト中に置換できる、変数の文字列値を指定する行です。簡単なmakefileの例では、すべてのオブジェクトファイルのリストを値とする`objects`変数を定義しています（{{0|変数でMakefileを簡単にする}}を参照）。

- *ディレクティブ*は、makefileを読み込んでいる間に、特別な処理を行うよう`make`に指示するものです。たとえば、次のような処理があります。
  - ほかのmakefileを読み込む（{{0|ほかのMakefileの読み込み}}を参照）。
  - makefileの一部を使うか無視するかを、変数の値に基づいて決める（{{1|Makefileの条件付き部分}}を参照）。
  - 複数行を含む文字列をそのまま使って変数を定義する（{{2|複数行の変数の定義}}を参照）。

- makefileの行にある`#`は、*コメント*の開始を表します。`#`とそれ以降の行の内容は無視されます。ただし、行末のバックスラッシュが別のバックスラッシュでエスケープされていない場合、コメントは複数行にわたって続きます。コメントだけを含む行（その前に空白があってもかまいません）は、実質的に空行であり、無視されます。文字としての`#`が必要な場合は、バックスラッシュでエスケープしてください（例：`\#`）。コメントはmakefileのどの行にも書けますが、特定の状況では特別に扱われます。

  変数参照や関数呼び出しの中ではコメントを使えません。その中にある`#`はすべて、コメントの開始ではなく、文字そのものとして扱われます。

  レシピ中のコメントは、ほかのレシピのテキストと同じようにシェルへ渡されます。解釈の方法はシェルが決めます。それがコメントかどうかは、シェル次第です。

  `define`ディレクティブの中では、変数を定義するときにコメントは無視されず、そのまま変数の値に保持されます。変数を展開すると、評価する文脈に応じて、`make`のコメントまたはレシピのテキストとして扱われます。

#### 3.1.1 長い行の分割

makefileは「行単位」の構文を使います。改行文字には特別な意味があり、文の終わりを示します。GNU `make`では、コンピュータのメモリ量が許す限り、文の行の長さに制限はありません。

ただし、折り返しやスクロールなしでは表示できないほど長い行は、読みにくくなります。そこで、文の途中に改行を入れ、makefileを読みやすい形に整えられます。途中の改行は、バックスラッシュ（`\`）でエスケープします。区別が必要な場合、エスケープの有無にかかわらず、改行で終わる1行を「物理行」と呼びます。一方、最初のエスケープされていない改行までの、エスケープされた改行をすべて含む完全な文を「論理行」と呼びます。

バックスラッシュと改行の組み合わせの扱いは、その文がレシピの行か、それ以外の行かによって異なります。レシピの行での扱いは、後で説明します（{{0|レシピの行の分割}}を参照）。

レシピの行以外では、バックスラッシュと改行は1つのスペース文字に変換されます。その後、その前後の空白類はすべて1つのスペースにまとめられます。これには、バックスラッシュの直前にあるすべての空白類、その改行後の行の先頭にあるすべての空白類、連続するバックスラッシュと改行の組み合わせも含まれます。

特殊ターゲット`.POSIX`が定義されている場合は、POSIX.2に準拠するため、この扱いが少し変わります。第1に、バックスラッシュの直前の空白類は削除されません。第2に、連続するバックスラッシュと改行はまとめられません。

#### 空白を追加せずに分割する

行を分割したいけれど、空白を追加し*たくない*場合は、少し巧妙な方法を使えます。バックスラッシュと改行の組を、ドル記号、バックスラッシュ、改行という3文字に置き換えます。

`make`がバックスラッシュと改行を取り除き、次の行との間を1つのスペースにまとめると、次と同等になります。

その後、`make`は変数を展開します。変数参照`$ `は、「 」（スペース）という1文字の名前の変数を参照します。この変数は存在しないため空文字列に展開され、最終的な代入は次と同等になります。
