There is the original file(in English) here.
最初,,,最後のページ,目次 に移動.

ルール行でのコマンドの記述

 ルールではコマンドはシェルコマンドで実行していく一行一行から成り立っています。コマンド行ではそれぞれの行をタブから始めなければなりません。ただし、最初のコマンド行はターゲットと依存関係行の最後にセミコロンをつけて、その直後に続ける事もできます。何もない行(Blank lines)やコメントだけの行がコマンド行の間にあってもよく、その場合はその部分は無視します。(ただし、気をつけておいて下さい。真に"空白(blank)"の行(タブで始まっている行)である場合は何もない(blank)行ではありません!そういう行は空のコマンドになります。これについては空のコマンドの利用の項を参照して下さい。)

 ユーザーはそれぞれに異なったシェルプログラムを使っていて、その種類は数多くありますが、makefileが他の方法を指定しない限りはmakefileのコマンドは常に`/bin/sh'で処理します。コマンド実行の項を見て下さい。

 コマンド行でコメントを使えるかどうか、その構文はどんなものか、という事は使用するシェルによって決まります。`/bin/sh'がシェルの時は、コメントは`#'から行末までになります。`#'は行の始めじゃなくても構いません。また、`#'の前のテキストはコメントにはなりません。

コマンドエコー

 makeは普通コマンドを実行する前に、実行するコマンドを画面に表示します。あなたが入力したコマンドを表示することからこの機能の事をエコー(echoing=反響)といいます。

 `@'ではじまる行はエコーせず、また`@'はシェルでコマンドを処理する前に除外されます。この機能の典型的な使い方として、makefileの処理過程を示すためのechoコマンドのように、出力のみが目的のコマンドを対象として使います。


@echo 配布ファイルの作成について


 make`-n'フラグか`--just-print'フラグを与えると実行する事なく処理内容を全てエコーします。これについてはオプション要約の項を参照して下さい。この場合、というよりも唯一この場合だけは`@'で始まる行も表示します。このフラグはmakeが必要とするコマンドを実際に実行せずに知るのに便利です。

 `-s'フラグか`--silent'フラグを使えば全部の行に`@'をつけたような動作をし、全くエコーしなくなります。makefileに特別なターゲットの.SILENTを依存関係なしで記述するのも同じ効果になります(特別なビルトイン・ターゲット名の項を参照)。さらに柔軟な機能を持った`@'があるので本質的には.SILENTは廃れた機能です。

コマンドの実行

 ターゲットを更新する際、実行するコマンドは各行それぞれで新しいサブシェルを使って処理されます。(実際のmakeの内部実装ではもっと処理を簡略化しています。)

重要: このことはcdのようにローカル変数をセットするシェルコマンドを使ってもそれ以後のコマンド行に影響しない事を示唆しています。(2) 次のコマンドにcdの結果を反映させるには、セミコロンを使って一つの行に二つのコマンドを書けばmakeがそれを一つのコマンドであると判断して二つ続けて一つのシェルで処理してくれます。以下がその例です。


foo : bar/lose
        cd bar; gobble lose > ../foo

 一つのシェルコマンドを複数の行に分けて記述したければ各分割行の最後以外の行末にバックスラッシュをつければそうできます。この複数にわたる行ではシェルに渡される前にバックスラッシュと改行(newline)が並ぶものは削除して、その結果としてできた一行をシェルに渡します。それゆえに以下のものは前述の例と全く同意です。


foo : bar/lose
        cd bar;  \
        gobble lose > ../foo

 シェルとして呼び出すプログラムはSHELL変数で指定でき、その指定をしなければデフォルトとして`/bin/sh'を使います。

 MS-DOSではSHELLをセットしなかった場合、(デフォルトで常にセットしてある)COMSPEC変数の値を代わりにシェルプログラムとして呼び出します。

 MS-DOS環境ではSHELL変数をMakefileでセットしたときの動作が異なります。 標準的なシェルである`command.com'があまりにもバカげた機能に限られているためにmakeのユーザーの多くは代わりのシェルをインストールする傾向にあります。このためMS-DOSではmakeSHELLの値で指定したシェルがUnix形式かDOS形式かで動作を変えます。このおかげでSHELL`command.com'を指定しても理に適った機能性を提供します。

 MS-DOS環境でSHELLにUnix形式のシェルを指定した場合、さらにmakeはそのシェルを実際に探して存在するかを調べます。探して見つからないとSHELLを指定している行を無視します。MS-DOS環境ではGNU makeはシェルを次に示す場所から検索します。

  1. SHELLの値で指定したのと寸分違わぬ場所。例えばmakefileで`SHELL = /bin/sh'と指示してあるのならmakeが探す場所はカレントドライブの`/bin'というディレクトリです。
  2. カレントディレクトリ。
  3. PATH変数にあるディレクトリ全部(探す順番は指定順に同じ)。

 makeはそれぞれの試行ディレクトリで、まず第一に(上の例の`sh'のような)指示ファイルを探します。それで見つからなければ実行可能ファイルを見分けるものとしてよく知られた拡張子を指示ファイルに一つ付加してそれも探します。例えば`.exe',`.com', `.bat', `.btm', `.sh'などです。

 試行した結果どれかが成功すれば見つかったシェルのフルパスをSHELLの値としてセットします。また、試行作業を通して全く発見できなければSHELLの値が変わる事はないため、変数指定行は事実上無視された事になります。以上のことから、makeを実行する環境にUNIX形式のシェルが実際にあれば、makeはUnix形式のシェル特有の機能だけをサポートすることになる、という結果になります。

 このシェル用拡張サーチ機能という機能はMakefileでセットしたSHELLだけに限られており、コマンドラインや環境でのセットではシェルのUNIXにある通りのフルパスをセットしなければならない事に気をつけておいてください。

 PATH変数に入れたディレクトリに例えば`sh.exe'がインストールしてあって、(UNIXのmakefileでするように)このまま`SHELL = /bin/sh'とMS-DOSのMakefileで書く場合にDOS環境特有の処理が行われます。

 他の多くの変数と違ってSHELL変数は環境からの指定を受け付けません。これは対話用のシェルプログラムとしてユーザーが選択したシェルを指定するために環境変数SHELLがあるからです。makefileの処理にユーザー指定のものが影響するのは 最悪です。これについては環境からの変数の項を見て下さい。ところがMS-DOSとMS-Windows上ではほとんどのユーザーがこの変数を指定しないので、環境変数SHELLの値を利用します。このことからほとんどmakeで使うためだけにこの環境変数を設定できます。 MS-DOS環境ではSHELLでの設定がmakeに不適ならMAKESHELL変数にmakeに使わせるシェルを指定することもでき、指定した場合SHELLの値を上書きします。

並列実行

 GNU makeでは複数のコマンドを一度に実行させることもできます。makeは一度に一つのコマンドを実行し、そのコマンドが終了するのを待って次のコマンドを実行するのが通常の動作ですが、make呼び出し時に`-j'オプションか`--jobs'オプションを使えばたくさんのコマンドを同時に実行するようになります。

 MS-DOSではマルチプロセスをサポートしていないため、`-j'オプションは無効になります。

 `-j'に整数を続ければそれがジョブスロットの数、すなわち一度に実行するコマンドの数になります。 `-j'オプションの後に整数らしきものを全くつけなければ、ジョブスロットの数に制限されなくなります。ジョブスロットのデフォルトの数は1で、これは直列実行(一度に一つしか実行しない)ということになります。

 複数コマンドの同時実行のひとつの欠点は、複数のコマンドが同時に出力をすればその全ての出力を受けることになり、その結果別々のコマンドが出力したメッセージがそれぞれバラバラになってしまう事です。

 もう一つの欠点は二つのプロセスが同じデバイスから入力を受けることはできないため、make は一度にたった一つのコマンドだけでもターミナルからの入力をちゃんと受けさせたいので実行している一つを除き全てのコマンドの標準入力ストリームを無効にしてしまいます。この結果、標準入力読み込みという試行作業は、マルチプロセスだと大抵ほとんどの子プロセスで(`パイプの欠陥(Broken pipe)'シグナルという)致命的(fatal)エラーを出すことになるのです。

 どのコマンドが有効な標準入力ストリーム(ターミナルからのもの、またはmakeでリダイレクト(置き換え)するようにあなたが指定した標準入力)を使っているかは予想できないことです。内部では一番最初のコマンド実行は常に最初に標準入力ストリームを取得し、それが終了した直後に開始したコマンドが次にそれを取得する…というようになるからです。

 もしも、現状のものよりも良い方法を発見したならmakeの動作を変えるつもりです。まだ劣悪な動作をしている現在は、標準入力を使うコマンドは並列処理に頼らず、標準入力を使うコマンドでも全く通常に動作してくれる(デフォルトの)直列処理を使うべきです。

 あるコマンドが(シグナルによる中断か、非ゼロのステータスを返したかで)失敗し、エラーになったコマンドを無視しない設定(コマンド内エラーの項を参照)であれば残されたコマンド行のうち同ターゲットの更新をおこなう行は無視されることになります。`-k'オプションか`--keep-going'オプションをつけていない場合(see section オプション要約の項を参照)はコマンドが失敗するとmakeの処理を中断します。 makeが複数の子プロセス実行中に(シグナルを含め)何らかの理由で終了する時は全部が終わるのを待ってから終了します。

 システムの負荷が重い(大きい)場合、多分負荷が軽い(小さい)時よりもジョブ実行数を少なくしてほしいと思います。`-l'オプションをつければmakeはジョブ実行数の平均に基づいて一度に実行するジョブの数を制限してくれます。`-l'オプションと`--max-load'オプションには浮動小数を続けて使います。
例えば…


-l 2.5

とすれば、負荷平均が2.5を超えた時はmakeに一つもジョブを開始させません。`-l'オプションに数値をつけないものは一つ前に`-l'オプションで与えられた負荷制限を解除する効果があります。

 makeがすでに一つ以上のジョブを実行していてこれから一つのジョブを開始させようとしている時は最も、現在の負荷平均のチェックが正確になります。具体的には `-l'で与えた制限以上の時にmakeの処理を、負荷平均が制限以下になるか他のジョブが全部終わるまで待たせるようになります。

デフォルトでは負荷制限はありません。

コマンド内エラー

 makeは各シェルコマンドの終了後に戻り値(exist status)を調べます。コマンドが完全に成功したら次の行を新しいシェルで実行し、最後のコマンド行が終了すればルールの処理が完了した事になります。

 エラーがあった(戻り値(exit status)がゼロ以外なった)場合makeは現在のルールの処理を諦めて、それから多分全てのルールでも諦めることになります。

 ある種のコマンドは失敗しても問題にはなりません。例えばmkdirコマンドを確実にディレクトリを存在させるために使う事ができるのですが、mkdirを使ったときにすでにディレクトリが存在していた場合エラーを報告します。しかしあなたは、makeにこのエラーを無視して続けさせたいと思うはずです。

 そういうとき、コマンド行の本文の初め(先頭のタブの直後)に`-'と書けばそのコマンド行でのエラーを無視させることができます。`-'はシェルにコマンドを渡して実行させる前に削除されます。

 例えばこうします。


clean:
        -rm -f *.o

 この場合rmがファイルを削除できなくても先を続けさせるようになります。

 `-i'フラグか`--ignore-errors'フラグをmakeにつけると、全てのルールの全てのコマンドのエラーを無視するようになります。makefileで.IGNOREという特別なターゲットを依存関係なしで書いたルールも同じ効果があります。`-'のほうが用途に富むのでこれらの機能は時代遅れのエラー無視手段です。

 `-'`-i'フラグでエラーを無視させると、makeは対象となったコマンドがエラーになった時に返り値のコード(exist status code)を出力してエラーが無視された事を報告する以外は成功したものと同然に処理します。

 makeに無視するように命令していないエラーが起こる事は、現在のターゲットどころか、それに直接的または間接的に依存するいかなるターゲットも正確に更新されていない可能性がある事を示唆しています。そういうターゲットに対するコマンドは仮定条件が達成されていないために、もはやそれ以上実行されません。

 こういう状態では普通、ゼロ以外のステータスが返されると直ちに中断します。ところが`-k'フラグか`--keep-going'フラグを指定すると中断してゼロ以外のステータスを返す前に、必要であればやりかけのターゲットの残りの依存関係を更新させます。例えば、あるオブジェクトファイルをコンパイルするときにエラーが発生してリンクが不可能だとわかっていても`make -k'なら他のオブジェクトをコンパイルし続けます。これについてはオプション要約の項を見て下さい。

 通常は指定したターゲットを更新する事を目的だと仮定して動作するため、それが不可能だと分かるとmakeは直ちに失敗を報告するようにします。`-k'オプションは真の目的がプログラム作成作業での変更をできるだけ多くテストすることにあると命令し、次回コンパイルさせる時までに完全に問題を修正しておくのに独立したいくつかの問題を発見するのを助けます。Emacsのcompileコマンドではこういう理由からデフォルトで`-k'フラグを渡します。

 コマンドが失敗したのに少しでもターゲットファイルが変更されていたなら、そのファイルは劣化して使えなくなった事になります。完全に更新されていなくても、です。ファイルのタイムスタンプがもう新しいのだから次回のmakeの動作でそのファイルを更新しようとする事もなくなります。これはコマンドがシグナルで中断された時と全く同じです。これについてはmakeを邪魔するか中断させるの項を見て下さい。だからファイルを変更し始めた直後にコマンドが失敗した場合、ターゲットファイルを削除する事が一般的には正しい事であり、.DELETE_ON_ERRORをターゲットにするとmakeはそう動作します。このことはほとんど毎回makeにやって欲しい事なのですが、これは歴史的な動作ではないため、互換性を維持するために明示的にリクエストしなければならない仕様になっています。

makeを邪魔するか中断させる

 makeのコマンド実行中にやめさせるシグナル(合図; a fatal signal)を出すと、コマンドで更新することになっていたターゲットファイルは削除されます。ターゲットファイルの最終修正日がmakeが最初にチェックした時から変更されていた場合にこの削除作業が行われます。

 ターゲットを削除するのは次回のmake実行で削除された状態から新しくちゃんと作らせるのが目当てです。どうしてか? もしあなたがコンパイラ実行中に[Ctrl]+Cと入力し、もうその時は既に`foo.o'というオブジェクトファイルを操作し始めていたとします。すると[Ctrl]+Cがコンパイラの実行を中止し、`foo.c'というソースファイルより最終修正時刻が新しいのに不完全なファイルが残ってしまいます。しかしmake[Ctrl]+Cというシグナルを受け取るので不完全なファイルを削除してくれます。makeがもしもそうしなければmakeが次回作動した時`foo.o'は更新の必要がないと考えてしまい、リンカが一部欠落したオブジェクトファイルをリンクしようとし、その結果おかしなエラーメッセージを出すことになります。

 .PRECIOUSという特別なターゲットにターゲットファイルを依存させればそのターゲットファイルの削除を防ぐことが可能です。makeはターゲットを更新する前に.PRECIOUSの依存関係に対象のターゲットがないかを調べ、そこからシグナル発生時にターゲットを削除すべきかを判断します。削除させない理由には、ターゲットを微小にしか更新しないため、とか、(中身によらず)修正時刻を記録するためだけにあるターゲットである、とか、別の類のトラブルを防ぐためにどんな時も存在していなければならないターゲットである、といったものがあります。

makeの再帰利用

 makeの再帰利用とはmakeをmakefileのコマンドとして使う事を指しています。このテクニックは大きなシステムを構成するのにそれより小さい様々なサブシステムのmakefileをその分割ファイルとして使う場合に役立ちます。例えば、`subdir'というサブディレクトリにmakefileがあり、そのディレクトリの親ディレクトリにあるmakefileでそのサブディレクトリでのmakeを実行させたいとすると、こういう風に書くことで実現できます。


subsystem:
        cd subdir && $(MAKE)

また、こうしても同じです(オプション要約の項を参照)。


subsystem:
        $(MAKE) -C subdir

 この例をそのままコピーすればmakeコマンドの再帰呼び出しを使えますが、どう動くのか、なぜそう動くか、それにサブ(下位)のmakeとトップレベルのmakeがどう関連するのか、という事については知っておくべき事が数多くあります。

 利便性からGNU makeではCURDIRという変数にカレント・ワーキング・ディレクトリ(現在の作業の中心になっているディレクトリ)にパス名をセットします。-Cを使うと元のものではなく新しいディレクトリのパスが有効になります。この値はmakefileの中でセットするのと同じ優先順位を持ちます(デフォルトでは環境変数CURDIRはこの値を上書きしません)。この変数をセットしてもmakeの作業に影響がないことに注意しておいてください。

MAKE変数はどう作用するか

 makeコマンドの再帰呼び出しでは`make'とコマンド名を明示せず、以下のようにMAKE変数を常に使うべきです。


subsystem:
        cd subdir && $(MAKE)

 この変数の値には現在作動中のmakeのファイル名が入っています。このファイル名が`/bin/make'というものなら、上のコマンドは`cd subdir && /bin/make'と解釈して実行します。トップレベルのmakefileで特別版のmakeを使っているなら再帰起動でも同じ特別版のものを実行してくれます。

 特別な機能として、`-t' (`--touch'), `-n' (`--just-print'), `-q' (`--question')の各オプションはMAKE変数をmakefileのコマンド内で使うと影響を違った効果になります。MAKE変数を使うのと`+'という文字をコマンド行の初めに使うのは同じ効果があります。これについてはコマンドを実行する代わりに…の項を見て下さい。

 前述の例で`make -t'というコマンドを使った場合を考えて下さい。(`-t'オプションは実際のコマンドの実行なくしてターゲットを更新させたという印をつけるもので、これについてはコマンドを実行する代わりに…の項に書かれています。) `-t'の一般定義に基づけば`make -t'コマンドを例で使うと`subsystem'というファイルを作成する以外は何もしない事になります。本当にして欲しいことは`cd subdir && make -t'を実行することなのに、このコマンドの実行を要求しても`-t'が何もコマンドを実行しないように命令してしまいます。

 MAKE変数がルールのコマンド行中にある時は常に、`-t'`-n'`-q'というフラグをその行に適用しない、という特別な機能が働くお陰で、して欲しい事をちゃんとやってくれるようになります。MAKEを含むコマンド行ではコマンドを実行させなくするフラグがあるにもかかわらず普通に実行されます。MAKEFLAGSのメカニズムのほうは、いつもどおり下位のmakeにフラグを渡すので(サブmakeにオプションを伝えるの項を参照)、サブシステムにファイルのタッチ(touch)やコマンドの出力といった希望の動作は継承されます。

サブmakeに変数を伝える

 明示的に要求すればトップレベルのmakeから下位(サブ)のmakeに変数の値を環境を通して渡すことができます。渡せる変数は下位のmakeでデフォルトでも定義されていますが、`-e'スイッチを使わなければmakefile内で指定した値のうち下位makeのmakefileでも使われるものをデフォルト値が上書きする事はありません(オプション要約の項を参照)。

 makeは変数を受け継がせる、つまりエクスポート(export)する事を、実行中の各コマンドに対して目的の変数と値を環境に追加する事で実現しています。そうしてから次に下位のmakeが変数の値の表(table of variable values)を環境を使って初期化します。これについては環境からの変数の項を見て下さい。

 makeに明示的な要求をしない場合、初めに環境で定義したかコマンド行でセットした変数だけしかエクスポートせず、エクスポートする変数名はアルファベット、数字、アンダースコア("_")のみで構成される名前でなければなりません。いくつかのシェルでは環境変数の名前にアルファベット、数字、アンダースコア以外の文字が非対応になっています。

 特別な変数であるSHELLMAKEFLAGSは(そうさせないようにしない限り)常にエクスポートされます。MAKEFILESは何かをセットした場合にエクスポートされます。

 makeはコマンド行で定義した変数の値を自動的にMAKEFLAGSに取り込んで下位に渡します。これについては次の項を見て下さい。

 makeでデフォルトで作成される変数は、普通は下位に渡されません(暗黙ルールに用いられる変数の項を参照)。サブのmakeではこういう変数を独自に定義します。

 特定の変数をサブmakeにエクスポートするにはexportディレクティヴをこうやって使います。


export 変数 ...

 ある変数をエクスポートしたくなければunexportディレクティヴをこうやって使います。


unexport 変数 ...

 次のようにすれば変数定義とエクスポートを同時にできてお手軽です。


export variable = value

は、下のものと同様の結果になります。


variable = value
export variable

それから、


export variable := value

は、下のものと同様の結果になります。


variable := value
export variable

あと、


export variable += value

は、次のものと全く同様です。


variable += value
export variable

変数にもっと多くのテキストを入れるの項を見て下さい。

 おそらくシェルshで動作するexportディレクティヴとunexportディレクティヴと同じ方法でmakeでも二つのディレクティヴが動作していることに気づくと思います。

 全ての変数をデフォルトでエクスポートしたいなら次のようにexportを単体で使って下さい。


export

 こうするとexportunexportかのディレクティヴで明示していないものをエクスポートするようにmakeに指示します。unexportディレクティヴで個々に指定した変数についてはこの方法では敢えてエクスポートしません。デフォルトで変数をエクスポートさせるのにexportを単体で使うという方法だけでは、英数字か下線("_")以外を名前に含む変数はエクスポートされません。そういう変数もエクスポートするには、さらにそれだけをexportディレクティヴで個々に書かなければなりません。

 過去のバージョンのGNU makeでは単体でexportディレクティヴを使った時の動作がデフォルトでした。この動作に依存したmakefileで古いバージョンのmakeとの互換性を持たせたい場合はexportディレクティヴを使う代わりに.EXPORT_ALL_VARIABLESという特別なターゲットのルールを書いて下さい。こうすれば過去のmakeではこの部分が無視され、exportディレクティヴを使った場合に起こる構文エラーを避けられます。

 また、unexportを単体で使えばデフォルトで変数をエクスポートしないようにmakeに指示します。これはもともとデフォルトの動作なので、それより前に(多分インクルードしたmakefileのどれかで)exportが単体で使われている場合以外は指示する必要はありません。一部のコマンドをエクスポートし、残りをそうさせないようにするのに、単体のexportと単体のunexportを併用することはできません。単体のexportと単体のunexportのうち後のものがmakeの全部の動作を決定します。

 特別な機能として、MAKELEVELという変数が各階層において下位に渡していくと、MAKELEVELの内容は変わります。この変数の値は階層の深さを10進数値で示す文字列です。この値は`0'がトップレベル(最上階層)のmakeをあらわし、それから`1'がサブ(下位)のmake`2'がサブサブmake、というようになっています。この数値増加はmakeがコマンドのために環境をセットしたときに起こります。

 MAKELEVELの主な用途は条件分岐ディレクティヴでの判断(Makefilesの条件分岐部分の項を参照)であり、これを利用する事で再帰呼び出し時とあなたが直接実行した時とで動作を変えるmakefileを記述する事が可能になります。

 MAKEFILES変数は、サブ起動の全てのmakeコマンドでmakefileを追加利用させるのに使います。MAKEFILESの値はファイル名が空白で区切られたリストです。もしこの変数が深い層(outer-level)のmakefileで定義されると、それは環境を通して下に渡されて、通常のmakefileか指定したmakefileを読み込む前に読ませる、余分なmakefileのリストがサブのmakeに与えられたような動作をします。これについてはMAKEFILES変数の項を見て下さい。

サブmakeにオプションを伝える

 `-s'`-k'のようなフラグはMAKEFLAGSを通して自動的にサブ(下位)makeに渡されます。この変数はmakeが受けとったフラグ文字を自動的にmakeが格納したものです。だから、もし`make -ks'とすればMAKEFLAGSには`ks'という値が入ります。

 どのサブmakeも結果的にMAKEFLAGSから環境で値を受け取ることになります。動作としてはこの変数の値からフラグを取得し、そういう引数が与えられたように処理します。オプション要約の項を見て下さい。

 また、コマンド行で定義された変数はMAKEFLAGSを通してサブmakeに受け渡されます。MAKEFLAGSの値に`='を含んだ語句があるとmakeはそれをコマンド行にあるときと全く同様に変数定義として扱います。変数の上書きの項を見て下さい。

 `-C', `-f', `-o', `-W'の各オプションはMAKEFLAGSの対象外であり、これらオプションは下位継承されません。

 `-j'オプションは特例です(並列実行の項を参照)。このオプションに数値を設定した場合、MAKEFLAGSには指定したものではなくて常に`-j 1'が入る事になります。これはなぜかというと、もしも`-j'オプションがサブmakeにそのまま受け渡してしまうと、頼んでいた以上のジョブを並列実行してしまうことになるでしょう。可能な限り実行させるという意味で`-j' に何も数値の引数を付加しなければ、複数の無限は一つの無限を超えないため、そのまま下位にこの引数を継承します。

 他のフラグを継承させたくないならMAKEFLAGSの値をこういう風にして変更しなければなりません。


subsystem:
        cd subdir && $(MAKE) MAKEFLAGS=

 コマンド行での変数定義は実際にはMAKEOVERRIDESという変数の中に現れて、MAKEFLAGSがこの変数への参照を格納しています。コマンド行での変数定義は下位に継承させたくないがフラグだけは通常通りに継承させたい場合はMAKEOVERRIDESをこういう風にして空っぽにリセットすれば良いのです。


MAKEOVERRIDES =

 これはあんまり便利な事ではありません。ですが環境のサイズが限られていて、MAKEFLAGSの値でも情報量が上回るくらい小さいというシステムもあります。`引数のリストが長すぎる(Arg list too long)'というエラーが出た場合これが原因になっているのかもしれません。 (特殊ターゲット`.POSIX'がmakefileに現れるとPOSIX.2に厳格に従い、MAKEOVERRIDESの変更がMAKEFLAGSに影響しなくなります。おそらくこの事はあなたにとってどうでも良い事でしょう。)

 よく似た変数にMFLAGSというものも歴史的互換性の維持のためにあります。この変数はMAKEFLAGSと同じ値になりますが、コマンド行での変数定義を含まず、空っぽの時以外は常にハイフン("-")から始まります(MAKEFLAGSもハイフンから始まる事がありますが、それは一文字だけではない`--warn-undefined-variables'のようなオプションが最初にあった場合だけです)。次にあるように、MFLAGSは再帰呼び出しのmakeコマンドでは伝統的に明示的に利用することになっていました。


subsystem:
        cd subdir && $(MAKE) $(MFLAGS)

しかしMAKEFLAGSによって、今はもうこの慣習は余計なものになりました。makefileに古いmakeプログラムとの互換性を持たせたいなら、現在のmakeでも通用するこのテクニックを使って下さい。

 `-k'(オプション要約の項を参照)のような特定のオプションをmakeを毎回実行するときにセットさせるのにもMAKEFLAGS変数が役立ちます。単純に環境のMAKEFLAGSに値を入力しておけばいいのです。makefileに影響力を持たせるフラグを追加指定するのにmakefileのMAKEFLAGSにセットすることもできます。
(注意:MFLAGSではこういう事はできません。この変数は互換性のためだけにセットされるため、どのように値をセットしても、makeがこれを解釈することはありません。)

 makeが(環境からだろうがmakefileからだろうが)MAKEFLAGSの値を解釈するときには、まず初めにハイフンから始まっていないものにハイフンを付け加えます。そして値を空白に区切られた語句に切り離して、それぞれの語句をコマンド行で与えられたようにして処理していきます(`-C', `-f', `-h',`-o', `-W'とこれらのロングネーム版は例外的に無視されます。ちなみに無効なオプションについてはエラーを出しません)。

 環境のMAKEFLAGSに入力をする場合は、徹底的にmakeの動作に影響する、すなわちmakefileの目的やmake自身の目的を蝕むようなオプションはインクルードしないようにすべきです。例を挙げると`-t', `-n', `-q'オプションのうち一つでも変数に入力してしまうと、悲惨な結果になり、少なからず驚いてしまうような、イライラする効果が当然のように出てきます。

--print-directory オプション

 makeの再帰多重呼び出しを行う場合、`-w'オプションか`--print-directory'オプションを使うとmakeが処理を始めたディレクトリと処理を終えたディレクトリを目で見てずっと簡単に理解できます。たとえば、`/u/gnu/make'というディレクトリで`make -w'が実行された場合、makeは以下のような一文を出力するでしょう。


make: Entering directory `/u/gnu/make'.

今のが処理前のもので、次のような一文が処理完了後のものです。


make: Leaving directory `/u/gnu/make'.

 `-w'オプションは`-C'オプションが使われるとサブのmakeで自動的に有効になってくれるので、通常はこのオプションを指定する必要がありません。`--no-print-directory'で明示的に無効にするか、`-s'で沈黙するように命令した場合は、make`-w'を自動的に有効にすることはありません。

「コマンド連鎖の缶詰め」を定義する

 色々なターゲットを作るのに同じ一連のコマンドを使うのが役に立つことなら、defineディレクティヴで一続きになっているものを缶詰めのように一塊で定義すれば、そういうターゲットを対象とするルールで缶詰めにされた一連の処理を参照して利用できるようになります。この「一連の処理が入った缶詰」とは実際には変数なので、他の変数名と競合する名前をつけてはいけません。

 ここにあるのがコマンド連鎖の缶詰めの定義例です。


define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef

 この例ではrun-yaccが定義変数名で、endefが定義終了を示し、間にある行が目当てのコマンドになります。defineディレクティヴでは、缶詰めにされた処理の中では変数参照や関数呼び出しを展開せず、`$'という文字や括弧や変数名など全てのものが定義した変数の値の一部になります。 一字一句違わずに変数を定義するの項を見ればdefineについて全ての解説があります。

 この例の最初のコマンドでは、この缶詰化処理を使った全てのルールの依存関係の第一要素を対象にYaccを実行させます。Yaccが出力するファイルは常に`y.tab.c'という名前になっています。二つ目のコマンドで、この出力ファイルをルールのターゲットファイル名に変更(move)させます。

 缶詰化された処理を利用するには、ルールにある目的のコマンド群を変数に入れ替えて下さい。他にある変数と同じように代用できます(変数参照の基本の項を参照)。defineで定義された変数は再帰的に展開される変数であるため、defineの中であなたが記述した全部の変数参照はここでやっと展開されます。
 たとえば、


foo.c : foo.y
        $(run-yacc)

 run-yaccの値にある`$^'変数には`foo.y'が代入され、`$@'には`foo.c'が代入されることになります。

 これは現実的な例ですが、実のところはこうする必要がありません。なぜならmakeには処理に絡むファイル名を基準にコマンドを見出してくれる暗黙のルールがあるからです (暗黙ルールの利用の項を参照)。

 コマンドの実行中には缶詰化処理は、それぞれのルールの中で普通にタブをつけて書いた場合と同じように扱われます。さらに詳しくいえば、makeは各行でばらばらのサブシェルを起動します。(`@', `-', `+'という)特別な接頭語を使って缶詰化処理内のコマンド行の動作に影響を与えることも可能です。ルール行でのコマンドの記述の項を見て下さい。
 たとえばこれも缶詰化処理として使えます。


define frobnicate
@echo "frobnicating target $@"
frob-step-1 $< -o $@-step-1
frob-step-2 $@-step-1 -o $@
endef

 makeechoコマンドを使う最初の行をエコーさせません。しかし、下に続く二つのコマンド行はちゃんとエコーしてくれます。

 また、缶詰化処理を参照するコマンド行で頭につけた文字(接頭語)は缶詰内の処理の全ての行に適用されます。このため、下のルールでは…


frob.out: frob.in
	@$(frobnicate)

 どのコマンドでもエコーさせません。 (コマンドエコーの項を見れば`@'についての全情報があります。)

空のコマンドを使う

 何もさせないコマンドを定義するのが便利な場合もあります。この定義は空白だけから成るコマンドを単純に与えるだけでいいのです。
 たとえば、


target: ;

とすると、`target'を対象に空っぽのコマンド文字列を定義します。空っぽのコマンド文字列を定義するのにタブ文字から始まる行を用いることも可能ですが、こういう行は見かけ上はまったく空っぽのように見えるだけなので混乱の原因に成りかねません。

 何もしてくれない空っぽのコマンド文字列を定義するのにどういう意義があるのか疑問に思われるでしょう。便利だという唯一の理由は、ターゲットが暗黙のコマンド(暗黙のルールや.DEFAULTという特別ターゲット)を利用するのを防ぐ事にあります(これについては暗黙ルールの利用の項と最後の手段を定義するデフォルトルールの項を見て下さい)。

 多分、依存関係を更新させるためだけにある実際には存在しないファイルをターゲットとするルールに空っぽのコマンド文字列を定義することに心が揺れたと思います。ですが、こうするとターゲットファイルがちゃんと存在してしまうと依存関係が更新されなくなってしまうので、これは最良の方法ではありません。もっといい方法が偽りのターゲット(Phony)の項にあります。


最初,,,最後のページ,目次 に移動.