7    make ユーティリティによるプログラムのビルド

make ユーティリティは,プログラムの最新バージョンを作成します。make ユーティリティは,大規模なプログラミング・プロジェクトで,多数のソース・ファイルを組み合わせて 1 つのプログラムを作成したり,1 つの製品またはアプリケーションを構成するプログラム群を作成したりする場合などに最適です。

この章では,次の情報について説明します。

make コマンドには,ビルド処理の実行を制御したり変更したりするためのオプションが用意されています。make ユーティリティは,同じソース・ファイルの 2 つ以上のバージョンを保守するという問題は扱いません。

プログラムの保守に make ユーティリティを使用すると,次のことが実行できます。

オペレーティング・システムは,いくつかのバージョンの make コマンドを提供します。 この章では,省略時のバージョンの make(1) コマンドについて説明します。 この他のバージョンとしては, make(1) ではサポートしない機能を提供する make(1u) および make(1p) があります。 make(1p) は,POSIX 準拠の make コマンドです。

make(1) および make(1u) は,ベース・オペレーティング・システムのサブセットに含まれています。 make(1p) は,ソフトウェア開発環境 (Software Develpoment Environment) サブセットに含まれています。

詳細については, make(1)make(1u) および make(1p) を参照してください。 この章では, make(1) の機能について説明します。

7.1    make ユーティリティの動作

make ユーティリティは,ターゲットまたはターゲット・ファイルと呼ばれるプログラムの作成日と,従属ファイルまたは従属と呼ばれるターゲットを構成する各ファイルの日付とを比較することによって作動します。 ターゲットの従属ファイルの中にターゲットよりも新しいものがあれば,make は既存のターゲットを古いものと見なします。 この場合,make はコンパイルやリンクなど,必要な手順を実行してターゲットを再作成します。 従属ファイルはまた,同時にターゲットでもあります。 たとえば,実行可能プログラムは複数のオブジェクト・モジュールから作成されます。 オブジェクト・モジュールは,複数のソース・ファイルから作成されます。 ターゲットよりも新しい従属は,若い (younger) ファイルと呼ばれます。

make ユーティリティは,次の情報を使用します。

make ユーティリティはファイルのタイム・スタンプを使用します。 分散システム上で make を正しく作動させるには,ネットワーク上のすべてのシステムの日付および時刻が一致していなければなりません。

make ユーティリティは,次の段階的な手順でターゲット・ファイルをビルドします。

  1. 記述ファイル内のターゲット・ファイルの名前を見つける。

  2. 従属行と呼ばれるターゲットの従属を示す行を見つける。

  3. ターゲットの従属ファイルのすべてが存在することおよび最新であることを確認する。

  4. ターゲットがその従属に対して最新であるかどうかを判定する。

  5. ターゲットまたは従属のいずれかが古いものであった場合には,次のいずれかの方法を使用してターゲットをビルドする。

make が実行された時点で,従属行に記されたすべてのファイルが最新のものであれば,make は,ターゲットが最新であることを示して実行を停止します。 ターゲットよりも新しい従属がある場合,make は,古いターゲットだけを再ビルドします。 存在していないファイルは,古いものであると見なされます。

所定のターゲットに従属がない場合には,ターゲットは常に古いものと見なされ,make を実行するたびにターゲットは作り直されます。 make の処理は,再ビルドする必要のあるターゲットを決定する際にはトップダウン方式で行われ,実際の再ビルド時にはボトムアップ方式で作動します。

ターゲットをビルドするために,make ユーティリティがコマンドを実行する時点で,make は各マクロをその値に置き換えて各コマンド行を標準出力にエコーし,コマンドを実行します。 マクロについての詳細は,7.2.9 項を参照してください。make ユーティリティは,rmcc などの直接実行できるコマンドを新しいシェルを呼び出さずに実行します。 make ユーティリティは,新しいシェルのパイプやリダイレクションなどのシェル関数を指定した各コマンド行を実行します。

make ユーティリティは,記述ファイルのあるディレクトリで起動します。make コマンドの構文は,次のとおりです。

make [ [-f ] makefile ] [ options ] [ targets ] [ macro definitions ]

make ユーティリティは,コマンド行のエントリを確認して実行する動作を判断します。 まず make ユーティリティは,コマンド行 (等号を含むエントリ) のマクロ定義がある場合にはこれに値を割り当て,次に記述ファイルのマクロ定義に値を割り当てます。 コマンド行に定義されたマクロ名が記述ファイルにも定義されている場合,make はコマンド行の定義を使用し,記述ファイルの定義を無視します。

次に,make はオプションを確認します。make がサポートするオプションの一覧については, make(1) を参照してください。

make ユーティリティは,残りのコマンド行エントリをターゲット名であると解釈して,左から右の順にそれらのターゲットを処理します。 コマンド行にターゲットがまったく存在しない場合には,make は記述ファイルで最初に指定されたターゲットを処理して実行を停止します。

7.2    記述ファイル

記述ファイルには,ターゲットに含める従属とそれらの従属とプロシージャ内の他のファイルとの関係を定義して,ターゲットのビルド方法を make に指示します。 記述ファイルには,次の情報が含まれます。

make ユーティリティは,従属ファイルの日付を確認することによって,ターゲットを最新に保つためにビルドするファイルを決定します。 前回ターゲットをビルドした後に従属ファイルが変更されている場合,make は,そのターゲットを含めて,従属ファイルの変更によって影響を受けるすべてのファイルをビルドします。 ほとんどの場合記述ファイルは簡単に記述でき,何度も変更されることはありません。

通常 make ユーティリティは,makefile または Makefile と名付けられた記述ファイルを探します。 記述ファイル名として makefile または Makefile を使用し,その記述ファイルが存在するディレクトリで作業している場合には,オプションおよび引数を省略して make コマンドを入力すると,make が前回ターゲットをビルドしてから変更されたファイルの数にはかかわらず,最初のターゲットおよびその従属ファイルを更新します。 次の例のように,make ユーティリティに -f オプションを使用すると,省略時のファイル名の代わりに任意の記述ファイル名を指定することができます。

% make -f my_makefile
 

このオプションを使用することにより,複数の記述ファイルを同じディレクトリに保存することができます。

この節では,記述ファイルの次の事項について説明します。

7.2.1    記述ファイル・エントリの形式

記述ファイル・エントリの一般的な形式は,次のとおりです。

[target1 [ target2... ] ] [:] [ [:] ] [ [dependent...] ] [ [; ] commands ] [ [# ] comment... ]

大カッコ内の項目は省略可能です。 ターゲット (target) および従属 (dependent) は,文字,数字,ピリオド,あるいはスラッシュで構成される文字列によるファイル名です。make コマンドは,アスタリスク ( * ) および疑問符 ( ? ) などのワイルドカード文字を認識します。 ターゲット名を含む記述ファイルの各行は,従属行と呼ばれます。 従属行では,ターゲット名の後に,ターゲットをビルドするための処理手順を指定する 1 つまたは複数のコマンド行 (commands) が続きます。

make では,マクロの指定にドル記号 ( $ ) を使用するため,ドル記号 ( $ ) をターゲットおよび従属のファイル名に使用してはなりません。 同様に,定義した make マクロを参照する場合以外には,記述ファイル内のコマンドにドル記号を使用してはなりません。 マクロについては,7.2.9 項7.2.10 項,および7.2.12 項を参照してください。

記述ファイル内にコメント (comment) を書く場合には,番号記号 ( # ) を使用してコメント・テキストを開始してください。make ユーティリティは,番号記号以降にある同じ行上の番号記号とすべての文字を無視します。 空白行も無視されます。

バックスラッシュ ( \ ) を行の終わりに置くことによって,入力デバイスの行幅よりも長い行を入力することができますが,この方法でコメント行を拡張してはなりません。 各行に 1 つの番号記号を付けて新しいコメント行を開始してください。

7.2.2    記述ファイルでのコマンドの使用

コマンドは,番号記号や改行文字を除いた,任意の文字からなる文字列です。 コマンドは,従属行のセミコロン ( ; ) の後または従属行の直後の行に現れます。 従属行の後の各コマンド行は,単一のタブ文字で開始する必要があります。

記述ファイル内でターゲットにコマンド・シーケンスを定義する場合には,各ターゲットにコマンド・シーケンスを 1 つ指定するか,または特定の従属の集合に別のコマンド・シーケンスを指定します。

各ターゲットを使用するたびにコマンド・シーケンスを 1 つ使用するには,従属行のターゲット名に続けてコロン ( : ) を 1 つ使用します。 たとえば,次の例では,test というターゲット名とターゲットを作成するための従属ファイルの集合およびコマンドの集合が定義されています。

test:  dependency list1...
        command list...

.
.
.
test: dependency list2...  

ここに示されているように,1 つのターゲット名が,記述ファイル内の複数の箇所に,異なる従属リストを伴って現れますが,このターゲット名に関連付けられるコマンド・リストは 1 つだけです。make ユーティリティは,所定のターゲットのすべての従属行を見つけて,それらの従属リストのすべてを1つのリストに連結します。 従属のいずれかが変更された場合に,make は当該ターゲットをビルドするために 1 つのコマンド・リストにあるコマンド群を実行します。

特定のターゲット・ファイルをビルドするために,コマンドの集合を 2 つ以上指定する場合には,2 つ以上の従属定義を入力します。 各従属行には,ターゲット名の後にコロンを 2 つ ( :: ) 加え,その後に 1 つの従属リスト,および,従属リストのファイルのいずれかが変更された場合に make が使用するコマンド・リストを続けなければなりません。 たとえば,次の例ではターゲット・ファイル test をビルドするために 2 つの異なる処理を定義しています。

test:: dependency list1...
        command list1...

.
.
.
test:: dependency list2... command list2...  

make は,従属リスト list1 のファイルのいずれかが変更された場合にはコマンド list1 を,従属リスト list2 のファイルのいずれかが変更された場合には list2 を実行します。 衝突を避けるため,1 つの従属ファイルを従属リストの list1 および list2 の両方に指定することはできません。

注意

make は,先行する各コマンド行および後続のコマンド行から独立したものとして各コマンドを実行するので,たとえば,一定のコマンド (cd など) を使用する場合には注意が必要です。 次の例では,cd コマンドは,後続の cc コマンドには影響を与えていません。

test:  test.o
        cd /u/tom/newtest
        cc main.o subs.o -o test
 

cc コマンドに cd コマンドを作用させるには,次のように,両方のコマンドを同じ行に置いてセミコロンで区切ります。

test:  test.o
        cd /u/tom/newtest; cc main.o subs.o -o test
 

次のように,バックスラッシュを後続する行の先頭に置くことによって,複数の行からなるシェル・スクリプトをシミュレートすることができます。

test:  test.o
        cd /u/tom/newtest; \
        cc main.o subs.o -o test
 

これは,直前の例とまったく同じ作用をします。 バックスラッシュによって接続する各行 (この例では cd の行) には,バックスラッシュの前にセミコロンを置かなければなりません。

7.2.3    make ユーティリティのコマンド・エコーの防止

make が実行中のコマンドを標準出力にエコーしないようにするには,次の手順のうちの 1 つを実行します。

7.2.4    make ユーティリティのエラーによる停止の防止

いずれかのコマンドがゼロ以外の状態コードを返した場合,make ユーティリティは通常,実行を停止してエラーを表示します。

エラーで make が終了しないようにするには,次の手順のいずれかを実行します。

7.2.5    省略時の条件の定義

make がターゲットをビルドするにあたって,明示されたコマンド行や内部規則を見つけることができない場合には,記述ファイル中の省略時の条件を調べます。 この場合に make が実行するコマンドを定義するには,記述ファイル中に擬似ターゲット名 .DEFAULT: を使用し,その他の任意のターゲットの場合と同様に,省略時のコマンド・シーケンスを入力します。

擬似ターゲット .DEFAULT: は,エラー回復の手順や make ユーティリティの内部規則に定義されていないプログラムで,すべてのファイルをビルドするための一般的な手順として使用することができます。

7.2.6    make によるファイル削除の防止

不正のおそれのあるターゲット・ファイルを使用してビルドしないように,make は通常,途中でエラーが返された場合にはターゲット・ファイルを削除します。 エラーが検出された場合にも,make がファイルを削除しないようにするには,記述ファイル内に擬似ターゲット .PRECIOUS: を使用してください。 擬似ターゲット名の後に,セーブする必要のあるターゲット名を挙げてください。 コマンド行に -u オプションを指定した場合,make はチェックアウトされた RCS ファイルを削除しません。make が RCS と対話する方法についての詳細は, make(1) を参照してください。

7.2.7    簡単な記述ファイル

例 7-1 では,x.cy.c,および z.c の 3 つの C 言語ファイルをロードしてコンパイルすることによって,prog と名付けられたプログラムがビルドされます。 ファイル x.c および y.c は,defs という名前のファイルの中でいくつかの宣言を共有しますが,ファイル z.c はこれを共有しません。

例 7-1:  記述ファイルの例

# Make prog from 3 object files
prog:  x.o y.o z.o
# Use the cc program to make prog
        cc  x.o y.o z.o -o prog
 
# Make x.o from 2 other files
x.o:   x.c defs
# Use the cc program to make x.o
        cc  -c x.c
 
# Make y.o from 2 other files
y.o:   y.c defs
# Use the cc program to make y.o
        cc  -c y.c
 
# Make z.o from z.c
z.o:   z.c
# Use the cc program to make z.o
        cc  -c z.c
 

このファイルを makefile と名付けた場合,4 つのソース・ファイル x.cy.cz.c,および defs のいずれかのファイルを変更した後では,オプションも引数も使用しないで make コマンドを入力するだけで,prog の最新コピーを作成することができます。

7.2.8    記述ファイルの簡素化

記述ファイルをより簡単にするには,make ユーティリティの内部規則を使用します。make は,ファイル・システムの命名規則によって,必要な .o ファイルと対応する 3 つの .c ファイルを認識します。make には,ソース・ファイルからオブジェクト・ファイルを生成する処理 (cc -c コマンドの実行) も組み込まれています。 これらの内部規則を活用することによって,前述の記述ファイルは次のように簡素化されます。

# Make prog from 3 object files
prog:  x.o y.o z.o
# Use the cc program to make prog
    cc  x.o y.o z.o -o prog
 
# Use the file defs and the appropriate .c file
# when making x.o and y.o
x.o y.o:   defs
 

make が使用する内部規則については,7.2.14 項を参照してください。

7.2.9    マクロの定義

マクロとは,1 つまたは複数の名前の代わりに使用される別名のことで,長い文字列を短縮するために使用されます。 マクロは,記述ファイル内またはコマンド行上に定義することができます。 記述ファイル内にマクロを定義する方法は次のとおりです。

  1. 新しい行をマクロ名で開始する。

  2. 名前の後に等号 ( = ) を入力する。

  3. 等号の右にマクロ名が表す文字列を入力する。 文字列には空白を含めることができる。

マクロ定義では,等号の前後に空白を指定しても結果には影響を与えません。 ただし,等号の前にコロン ( : ) またはタブを指定することはできません。make ユーティリティは,マクロ定義の文字列に先行および後続する空白を無視します。 次にマクロ定義の例を示します。

# Macro ABC has a value of "ls -la"
ABC = ls -la
 
# Macro LIBES has a null value
LIBES =
 
# Macro DIRECT includes the definition of macro ROOT
# The expanded value of DIRECT is "/usr/home/fred"
ROOT   = /usr/home
DIRECT = $(ROOT)/fred
 

この例にある DIRECT マクロは,自身の定義の一部として別の定義を使用します。 マクロを使用する際の手順については,7.2.10 項を参照してください。

コマンド行上でマクロを定義するには,記述ファイル内でマクロを定義する場合と同じ構文に従いますが,同じ行の中にすべてのマクロを定義してください。 コマンド行上で空白を含んだマクロを定義する場合には,( "name = definition" ) のように引用符で定義を囲みます。 引用符を付けない場合,シェルは,空白がパラメータ・セパレータであり,マクロの一部ではないと解釈します。

7.2.10    記述ファイルでのマクロの使用

記述ファイルでマクロを定義した後に,マクロ名の前にドル記号 ( $ ) を置くことによって記述ファイルのマクロの値を参照します。 マクロ名が 1 文字より長い場合には,次の例で示されるように,カッコまたは中カッコで囲んでください。

$(CFLAGS)
${xy}
$Z
$(Z)
 

最後の 2 つの例は,同じ結果になります。

7.2.10.1    マクロの置換

マクロの定義値の一部またはすべてを,異なる値に置換することができます。 次に,マクロ置換の 3 つの形式を示します。

MACRO が定義されていない場合,形式 1 および 2 では空文字列が生成されます。

7.2.10.2    条件付きマクロ

マクロの値は,先在する条件に基づいて割り当てることができます。 このタイプのマクロを条件付きマクロと呼びます。 コマンド行で条件付きマクロを定義することはできません。 条件付きマクロ定義は,すべて記述ファイルに定義する必要があります。 条件付きマクロの構文は,次のとおりです。

[target:=MACRO = string]

指定されたターゲットが make コマンドの現在のターゲットである場合には,条件付きマクロには,文字列の値が割り当てられます。 そうでない場合は,マクロの値は空になります。 次の記述ファイルでは,MAC1 に条件付き置換を使用しています。

# Define the conditional macro MAC1
target2:=MAC1 = xxx yyy xxxyyy

.
.
.
#list targets and command lines # target1:;@echo $(MAC1) target2:;@echo $(MAC1)  

この記述ファイルを使用して make を実行した場合は,次のような結果になります。

% make target1
% make target2
xxx yyy xxxyyy
 

7.2.11    記述ファイルからの make ユーティリティの呼び出し

make 記述ファイル内のコマンド行の 1 つに $(MAKE) マクロを指定することによって,make ユーティリティの呼び出しをネストすることができます。 このマクロが存在する場合,-n オプションが設定された場合にも,make は,別の make のコピーを実行します。-n オプションについての詳細は,7.2.16 項を参照してください。

7.2.12    内部マクロ

make ユーティリティには,記述ファイル内で使用できる組み込みマクロ定義があります。 これらのマクロは,記述ファイル内での変数の指定を補助するものです。make ユーティリティは,マクロを表 7-1 に示された値に置換します。

表 7-1:  make の内部マクロ

マクロ
$@ 現在のターゲット・ファイル名
$$@ 従属行のターゲット名
$? ターゲットよりも新しく変更された従属ファイル名
$< 新しいターゲット・ファイルがビルドされる原因となった古いファイルの名前
$* サフィックスなしの現在の従属ファイル名

上記の内部マクロは,実際に make が使用する際に,単一のファイル名に変更されます。 サフィックス D を使用すれば上記マクロのいずれかの解釈を変更し,ファイル名のディレクトリ部分だけを指定することができます。 たとえば,現在のターゲットが /u/tom/bin/fred である場合に,$(@D) マクロは,名前の /u/tom/bin という部分だけを返します。 同様に,サフィックス F では,ファイル名の部分だけを返します。 たとえば,$(@F) マクロに同じターゲットを与えた場合には,fred を返します。$? マクロを除くすべての内部マクロは,サフィックス D あるいは F をとることができます。

分散ファイル・システムで内部マクロを使用する場合には,その前に,make が処理するファイルを含むすべてのノードで,システム・クロックが同じ日付と時間を示していることを確認する必要があります。

make ユーティリティは,記述ファイルからコマンドを実行してターゲット・ファイルをビルドする場合にだけ,これらの記号を変更します。 次の項では,これらのマクロの詳細について説明します。

7.2.12.1    ターゲット・ファイル名内部マクロ

make ユーティリティは,ターゲットをビルドするコマンド・シーケンスの中に出現するすべての $@ マクロを,現在のターゲットのフルネームに置換します。 この置換は,コマンドを実行する前に行われます。 次にその例を示します。

/u/tom/bin/test:  test.o
        cc test.o -o $@
 

この例では,/u/tom/bin/test という名前の実行可能ファイルが作成されます。

7.2.12.2    ラベル名内部マクロ

$$@ マクロが記述ファイルの従属行のコロンの右側で使用された場合,make はこの記号を従属行のコロンの左側にあるラベル名と置換します。 この名前は,ターゲット名や別のマクロ名であってもかまいません。 次にその例を示します。

cat:  $$@.c
 

make ユーティリティは,この行を次のように解釈します。

cat:  cat.c
 

このマクロを使用すると,各ファイルが単一のソース・ファイルを持つファイルのグループを作成できます。 たとえば,システム・コマンドのディレクトリを保守するには,次のような記述ファイルを使用します。

# Define macro CMDS as a series of command names
CMDS = cat dd echo date cc cmp comm ar ld chown
 
# Each command depends on a .c file
$(CMDS):  $$@.c
 
# Create the new command set by compiling the out of
# date files ($?) to the current target file name ($@)
        cc -O $? -o $@
 

make ユーティリティは,実行時に $$(@F) マクロを $@ のファイルの部分に変更します。 たとえば,記述ファイルを別のディレクトリで使用しながら usr/include ディレクトリを保守する場合に,この記号を使用することができます。 その記述ファイルは,次に示されるようになります。

# Define directory name macro INCDIR
INCDIR = /usr/include
 
# Define a group of files in the directory
# with the macro name INCLUDES
INCLUDES = \
         $(INCDIR)/stdio.h \
         $(INCDIR)/pwd.h \
         $(INCDIR)/dir.h \
         $(INCDIR)/a.out.h
 
# Each file in the list depends on a file
# of the same name in the current directory
$(INCLUDES):       $$(@F)
 
# Copy the younger files from the current
# directory to /usr/include
         cp $? $@
 
# Set the target files to read only status
         chmod 0444 $@
 

この記述ファイルは,現在のディレクトリで対応するファイルが変更された場合に,/usr/include ディレクトリでファイルを作成します。

7.2.12.3    younger ファイル内部マクロ

$? マクロが記述ファイルのコマンド・シーケンスにある場合,make$? をターゲット・ファイルの最後の変更後に更新された従属ファイルのリストに置換します。

7.2.12.4    最初の旧ファイル内部マクロ

$< マクロが記述ファイルのコマンド・シーケンスにある場合,make は,$< をファイルの作成を開始させたファイル名に置換します。 置換するファイル名は,当該ターゲット・ファイルに対して古くなった特定の従属ファイル,すなわち,make が当該ターゲット・ファイルを再度作成する原因となったファイルの名前です。 これが,新ファイルの一覧を返す $? 記号との違いです。

make ユーティリティは,内部規則から,あるいは,.DEFAULT: リストからコマンドを実行する場合に限り,この記号を置換します。$< 記号は,明示的に指定されたコマンド行には影響を与えません。

7.2.12.5    現在のファイル名プレフィックスのための内部マクロ

$* マクロが記述ファイルのコマンド・シーケンスにある場合,make$* を現在 make が使用してターゲット・ファイルをビルドしている従属ファイル名のサフィックスを除く部分に置換します。 たとえば,make がターゲット test.c を作成している場合,$* 記号はファイル名 test に相当します。

make ユーティリティは,内部規則から,あるいは,.DEFAULT: リストからコマンドを実行する場合に限り,この記号を置換します。$* 記号は,明示的に指定されたコマンド行には影響を与えません。

7.2.13    make による環境変数の使用

make は,実行されるたびに現在の環境変数を読み取って,定義済みのマクロに追加します。 さらに,MAKEFLAGS という新しいマクロを作成します。 MAKEFLAGS マクロは,コマンド行に入力されたすべてのオプションの集合です。 コマンド行オプションおよび記述ファイルの割り当てによっても,MAKEFLAGS マクロの値を変更することができます。make が別の処理を開始する場合には,別の処理に対して MAKEFLAGS をエクスポートします。MAKEFLAGS マクロの再帰的な make 処理の影響については,7.2.16 項を参照してください。

make ユーティリティは,次の順序でマクロ定義を割り当てます。 矛盾が発生する場合は上位の設定が優先します。

  1. MAKEFLAGS 環境変数を読み取り,変数に指定されたオプションを設定する。

    MAKEFLAGS が存在しないか,あるいは値が空の場合,make は内部 MAKEFLAGS マクロを空文字列に設定します。 そうでない場合,makeMAKEFLAGS の各文字が入力オプションであると見なします。make ユーティリティは,-f-p,および -r を除くこれらのオプションを使用して,動作条件を決定します。

  2. コマンド行にある入力フラグを読み取り,設定する。

    コマンド行で明示的に指定されたすべてのオプションが,MAKEFLAGS 環境変数によって設定に追加されます。

  3. コマンド行からマクロ定義を読み取る。

    これらの定義は,記述ファイル内の同じ名前の定義を変更します。

  4. 内部マクロ定義を読み取る。

  5. MAKEFLAGS マクロを含む環境変数を読み取る。

    make ユーティリティは,すべての環境変数をマクロ定義として扱い,コマンドを実行するために呼び出すシェルにそれらを渡します。

7.2.14    内部規則

make ユーティリティは,内部規則の集合を持ち,これを使用してターゲットをビルドする方法を決定します。-r オプションを付けて make を呼び出すことによって,これらの規則を変更することができます。 この場合,記述ファイル内のターゲットのビルドに必要なすべての規則を提供する必要があります。 内部規則には,擬似ターゲット .SUFFIXES: を使用して定義されるファイル名のサフィックスのリストが含まれます。 また,内部規則には,あるサフィックスを持つファイルから別のサフィックスを持つファイルを make に作成させる規則も含まれます。make の内部規則でサポートされる変換対象項目の一覧を参照するには,次のコマンドを実行してください。

% make -p | more
 

省略時の設定によるリストを変更しない場合,make は次のサフィックスがあるものと解釈します。

サフィックス ファイル・タイプ
.o オブジェクト・ファイル
.c C ソース・ファイル
.e efl ソース・ファイル
.r Ratfor ソース・ファイル
.f あるいは .F FORTRAN ソース・ファイル
.s アセンブラ・ソース・ファイル
.y yacc C ソース文法
.yr yacc Ratfor ソース文法
.ye yacc efl ソース文法
.l lex ソース文法
.out 実行可能ファイル
.p Pascal ソース・ファイル
.sh Bourne シェル・スクリプト
.csh C シェル・スクリプト
.h C ヘッダ・ファイル

1 つまたは複数のサフィックスをスペースで区切り,記述ファイルの .SUFFIXES: 行に加えると,上記のリストにサフィックスを追加することができます。 たとえば,次の行の例では,サフィックス .f77 および .ksh が既存のリストに追加されます。

.SUFFIXES: .f77 .ksh
 

make のサフィックスの省略時のリストを消去するには,何も名前を指定しないで .SUFFIXES: 行を挿入します。 1 行目に空のリストを,2 行目に新しいリストを入力すると,省略時のリストを完全に新しいものにすることができます。

.SUFFIXES:
.SUFFIXES: .o .c .p .sh .ksh .csh
 

make は,サフィックス・リストを左から右の順に調べるため,エントリの順序は重要です。 上記の例では,make がオブジェクト・ファイルを,次に C ソース・ファイルを検索します。

make ユーティリティは,リスト中にあり,次の 2 つの必要条件を満たす最初のエントリを使用します。

make が認識するリストにサフィックスを追加する場合には,従属からターゲットをビルドする方法を説明する規則を提供する必要があります。 規則は従属行とそれに対応する一連のコマンドと似ています。 make ユーティリティは,その規則が定義する 2 つのファイルのサフィックスから規則の名前を作成します。 たとえば,.r ファイルを .o ファイルに変える規則の名前は,.r.o です。例 7-2 は,標準の省略時の規則ファイルの一部です。

7.2.14.1    単一サフィックスの規則

make ユーティリティには,コマンド・ファイルなどのサフィックスを持たないターゲットをビルドするための,単一サフィックスの規則もあります。make ユーティリティには,次のサフィックスを持つソース・ファイルを,サフィックスを持たないオブジェクト・ファイルに変更する規則があります。

例 7-2:  省略時の規則ファイル

# Create a .o file from a .c
# file with the cc program
.c.o
        $(CC) $(CFLAGS) -c $<
 
# Create a .o file from either a
# .e , a .r , or a .f
# file with the efl compiler
        $(EC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<
 
# Create a .o file from
# a .s file with the assembler
.s.o:
 
       $(AS) -o $@ $<
 
.y.o:
# Use yacc to create an intermediate file
 
       $(YACC) $(YFLAGS) $<
# Use cc compiler
 
       $(CC) $(CFLAGS) -c y.tab.c
# Erase the intermediate file
 
       rm y.tab.c
# Move to target file
 
       mv y.tab.o $@
 
.y.c:
# Use yacc to create an intermediate file
 
       $(YACC) $(YFLAGS) $<
# Move to target file
 
       mv y.tab.c $@
 

サフィックス ソース・ファイルのタイプ
.c C 言語ソース・ファイルから
.sh シェル・ファイルから

たとえば,必要なすべてのファイルが現在のディレクトリにある場合に,cat のようなプログラムを保守するには,次のコマンドを入力します。

% make cat
 

7.2.14.2    make の組み込みマクロの変更

make ユーティリティは,内部規則としてマクロ定義を使用します。 これらのマクロ定義を変更するには,コマンド行または記述ファイルに,それらのマクロの新しい定義を入力してください。make ユーティリティは,コマンドおよび言語プロセッサに次のマクロ名を使用します。

コマンドまたは関数 コマンド・マクロ コマンド・オプションまたは他のマクロ
 
アーカイブ・プログラム (ar) AR ARFLAGS
アーカイブの目次作成   RANLIB
アセンブラ AS ASFLAGS
C コンパイラ CC CFLAGS
C ライブラリ   LOADLIBS
RCS チェックアウト CO COFLAGS
コピー・コマンド (cp) CP CPFLAGS
efl コンパイラ EC EFLAGS
リンカ・コマンド (ld) LD LDFLAGS
lex コマンド LEX LFLAGS
lint コマンド LINT LINTFLAGS
make コマンド MAKE  
再帰的 make 呼び出しフラグ   MAKEFLAGS
mv コマンド MV MVFLAGS
pc コマンド PC PFLAGS
f77 コンパイラ RC FFLAGS
Ratfor コンパイラ・フラグ   RFLAGS
rm コマンド RM RMFLAGS
従属ファイルと関係するファイルの配置   VPATH
yacc コマンド YACC YFLAGS
yacc -e コマンド YACCE YFLAGS
yacc -r コマンド YACCR YFLAGS

たとえば,次のコマンドは,make を実行して,既定の C 言語コンパイラを newcc プログラムに置換します。

% make CC=newcc
 

同様に,次のコマンドは,make に C 言語コンパイラによって作成された最終的なオブジェクト・コードを最適化するように指示します。

% make "CFLAGS=-O"
 

make が使用する内部規則を調べるには,Bourne シェルから次のコマンドを入力します。

$ make -fp -< /dev/null 2>/dev/null
 

出力は,標準出力に表示されます。

7.2.15    他のファイルのインクルード

記述ファイルの任意の行に最初のワードとして include を入力すると,現在の記述ファイルにファイルをインクルードすることができます。include の後に空白またはタブを続けて,次に make が実行中にインクルードするファイル名を入力します。 次にその例を示します。

include    /u/tom/temp /u/tom/sample
 

7.2.16    記述ファイルのテスト

記述ファイルをテストするには,-n コマンド・オプションで make を実行してください。 このオプションは,make にコマンド行を実行しないでエコーだけするように指示します。make が実行するプロセス全体がユーザに見えるように,アットマーク ( @ ) で始まるコマンドもエコーされます。-n オプションで実行中の場合でも,$(MAKE) マクロは,その他のコマンドとは違い実際に実行されます。

記述ファイルに $(MAKE) マクロのインスタンスが含まれる場合,make-n を含む,コマンド行に入力したオプションのリストを MAKEFLAGS マクロに設定した状態で,make の新しいコピーを呼び出します。make の新しいコピーは,-n オプションが設定されているため,新しいコピーを呼び出した make と同じ方法でコマンドの実行を無視します。make コマンドを 1 度実行するだけで,make を再帰的呼び出しする記述ファイルのセットをテストすることができます。

7.2.17    記述ファイル

例 7-3 は,make ユーティリティを保守するための記述ファイルの例です。make のソース・コードには,多くの C 言語ソース・ファイルおよび yacc 文法ファイルが含まれます。yacc についての詳細は,第 4 章を参照してください。

例 7-3:  make ユーティリティの makefile

# Description file for the Make program
 
# Macro def: send to be printed
P = lpr
 
# Macro def: source file names used
FILES = Makefile version.c defs main.c
 
      doname.c misc.c files.c
      dosy.c gram.y lex.c gcos.c
 
# Macro def: object file names used
OBJECTS = version.o main.o doname.o \
         misc.o files.o dosys.o gram.o
 
# Macro def: lint program and flags
LINT = lint -p
 
# Macro def: C compiler flags
CFLAGS = -O
 
# make depends on the files specified
# in the OBJECTS macro definition
make:    $(OBJECTS)
# Build make with the cc program
        cc $(CFLAGS) $(OBJECTS) -o make
# Show the file sizes
        size make
 
# The object files depend on a file
# named defs
$(OBJECTS):  defs
 
# The file gram.o depends on lex.c
# uses internal rules to build gram.o
gram.o:  lex.c
 
# Clean up the intermediate files
clean:
         rm *.o gram.c
 
# Copy the newly created program
# to /usr/bin and deletes the program
# from the current directory
install:
        cp make /usr/bin/make ; rm make
 
# Empty file ''print'' depends on the
# files included in the macro FILES
print:   $(FILES)
# Print the recently changed files
        lpr $?
# Change the date on the empty file,
# print, to show the date of the last
# printing
        touch print
 
# Check the date of the old
# file against the date
# of the newly created file
test:
        make -dp | grep -v TIME >1zap
        /usr/bin/make -dp | grep -v TIME >2zap
        diff 1zap 2zap
        rm 1zap 2zap
 
# The program, lint, depends on the
# files that are listed
lint:    dosys.c doname.c files.c main.c misc.c \
        version.c gram.c
# Run lint on the files listed
# LINT is an internal macro
        $(LINT) dosys. doname.c files.c main.c \
        misc.c version.c gram.c
        rm gram.c
 
# Archive the files that build make
arch:
        ar uv /sys/source/s2/make.a $(FILES)