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

5. ルールのなかでのコマンドの書き方

ルールの命令は、1行ずつ実行されるシェルコマンドの行で成り立っていて、 個々の行はタブで始まらなければなりませんが、あいだにセミコロンのある ターゲットと必要条件の行は例外です。また、空白行とコメントだけの行も あいだに置くことができますが、それらは無視されます。(ただし、タブで 始まり明らかに空白の行は空白ではなく空の命令です。 see section 空のコマンドの使用.。)

ユーザーは多くの異なったシェルプログラムを使用しますが、makefile中の コマンドはほかのシェルを指定しない限り、つねに‘/bin/sh’によって 解釈されます。See section コマンド実行.。

使用されるシェルは、コマンド行においてコメントが書かれているかどうか、 使用されるシンタックスは何かを決定します。シェルが‘/bin/sh’の場合、 ‘#’がコメントの始まりで、行の終わりまでコメントとされます。また、 ‘#’が行の先頭にある必要はなく、‘#’よりまえのテキストはコメントの 一部ではありません。


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

5.1 コマンドエコー

通常、makeはコマンドの実行前に個々のコマンド行を出力します。 コマンドをタイプしたときのように見えることからこれをエコーといいます。

行が‘@’で始まる場合、エコーは抑制され、コマンドがシェルに渡される まえに‘@’は破棄されます。一般的には、makefileを通して実行状態を 表示するためのechoコマンドのように何かを出力する効果のある コマンドに対してこれを用います。

 
@echo About to make distribution files

makeに‘-n’あるいは‘--just-print’フラグが 与えられる場合には、コマンドのエコーだけを行ない実行はしません。 See section オプションのサマリー.。 このケースにおいてだけ、‘@’で始まるコマンドでさえも出力されます。 このフラグは有益で、makeが必要とするコマンドがどれであるかを実行を 伴わずにみつけだすことができます。

-s’あるいは‘--silent’フラグがmakeに与えられた場合、 すべてのコマンドが‘@’で始まるかのごとくすべてのエコーが抑制されます。 必要条件を持たない特別なターゲットである.SILENTに対するmakefileの ルールは同様の効果を持ちます (see section 特別な組み込み済みのターゲット名.)。‘@’は より柔軟なため、.SILENTは本質的に時代遅れといえます。


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

5.2 コマンド実行

ターゲットをアップデートする命令の実行のタイミングであるとき、それぞれの 行に対して新しいサブシェルを作ることによって実行されます。(実際には、 makeは結果に影響を与えないショートカットを捉えます。)

[Please Note:]cdのような個々のプロセスにローカルな 変数をセットするシェルコマンドはそれに続く行に対して影響を与えないことを 意味していることです。(1) 仮に、cdを使用して次のコマンドに影響与えるようにする場合、1行に2つの コマンドをセミコロンで区切って置けばよいのです。そして、makeは それらを1つのコマンドのようにみなし、連続して実行するようにします。たとえば 以下のようになります。

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

もし、1つのシェルコマンドを複数の行に分割したい場合には、最後の行を除いて すべての行の終わりにバックスラッシュを置きます。このような連続した行は、 シェルに渡されるまえにバックスラッシュによる分割が削除されて単一の行として 統合されます。したがって、以下の例は前記のものと同じものとなります。

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

シェルとして使われるプログラムは変数.SHELLから得られます。 デフォルトでは、‘/bin/sh’が使われます。

MS-DOSの場合、SHELLがセットされていない場合には変数COMSPECの 値がかわりに用いられます。

Makefileにおいて変数SHELLをセットした行の処理はMS-DOSの場合には 異なります。もともとのシェルである‘command.com’は機能が滑稽に 制限されていて、makeのユーザーはかわりのシェルをインストールする 傾向があります。したがってMS-DOSにおいては、makeSHELL変数の 値を試し、UnixスタイルかDOSスタイルかによってふるまいを変更します。 これによって、たとえSHELLが‘command.com’であっても妥当な機能を 提供できるのです。

SHELLがUnixスタイルを示す場合、MS-DOSの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がサポートしているということです。

ここで、シェルのサーチについては、MakefileでSHELLがセットされて いる場合には制限されることを注意してください。環境変数やコマンドラインで 設定されている場合には、Unixの場合のようにシェルのフルパスにセットされる ことが必要です。

以上のDOS限定の処理の効果は、多くのUnixのmakefileのように ‘SHELL = /bin/sh’であるMakefileがMS-DOSでPATHに従う ディレクトリに‘sh.exe’がインストールされている場合に限られます。

大部分の変数と異なり、SHELLは環境から設定されることはありません。 これは、環境変数SHELLが対話的な使用をするシェルを個人の好みで指定 できるからです。しかし、個人の選択によることはmakefileの機能への影響としては 好ましくないのです。See section 環境(変数)からの変数の取得.。 しかし、MS-DOSやMS-Windowsにおいては環境変数のなかのSHELLの値が 用いられます。これらのシステムのユーザーはこの変数を設定しませんので、 makeによって使用されるように明確に指定する必要があります。また、 MS-DOSにおいてはSHELLのセッティングがmakeにとって適当ではない 場合にmakeが使用するMAKESHELL変数を設定することができ、 これはSHELLをオーバーライドします。


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

5.3 パラレル実行

GNUのmakeはいくつかのコマンドを同時に実行することができます。通常は makeは一度に1つのコマンドの実行しかせず、直前の処理の終了を 待ってから次の処理に移ります。しかしながら、‘-j’あるいは ‘--jobs’オプションがある場合は、makeは多くのコマンドを 同時に実行します。

ただし、MS-DOSにおいてはマルチプロセッシングをサポートしていないので、 ‘-j’オプションは意味がありません。

-j’オプションのあとに整数がつく場合は、同時に実行するコマンドの数を 表わし、これをジョブスロットの数といいます。‘-j’オプションの あとに整数がないときは、ジョブスロットに制限がないことを意味します。 ジョブスロットのデフォルトの値は1で、シリアルな実行を意味します。

同時にいくつかのコマンドを実行した際に不愉快なのは、種々のコマンドが出す メッセージがバラバラに出てくることです。

もう1つ別の問題は、2つのプロセスが同じデバイスから入力を得ることが できないことです。したがって、ターミナルからの入力を得ようとするコマンドが 一度に1つになるように気をつけなければならず、makeは標準入力を 無効にして1つのコマンドが動作するようにします。つまり、複数の 子プロセスに対する標準入力からの読み込みは通常はエラー (‘Broken pipe’シグナル)になるということです。

どのコマンドが有効な標準入力ストリーム(ターミナルまたはmakeの入力を リダイレクトするデバイス)であるかを予測することは困難です。つねに最初の コマンドの実行がそれを獲得して、その終了後に次々に獲得していきます。

ほかに選択肢があるならば、makeのこの特徴をどのように変更したいと 考えるでしょうか。パラレル実行を用いる場合には、標準入力を用いるいかなる コマンドも信頼しないでしょう。しかし、この機能を使用しない場合は標準入力は すべてのコマンドで正常に動作します。

最終的には、再帰的なmakeの呼び出しが問題として出てきます。詳細は、 サブのmakeへのオプションの伝達. を参照してください。

コマンドの実行が失敗した場合(シグナルでkillされるか、ゼロ以外の ステータスで終了した場合)、しかもエラーが無視されなかった場合 (see section コマンドのエラー.)、同じターゲットを再構成するための 残されたコマンドは実行されません。コマンドが失敗して‘-k’や ‘--keep-going’オプションが与えられないときには (see section オプションのサマリー.)、makeは実行を 中止します。子プロセス側の理由によってmakeが中断する場合には、 終了するまえに、それらの終了を待ちます。

システムのロード(負荷)が大きい場合、小さいときに比較して少ないジョブを 実行させようとするはずです。‘-l’オプションをつけることによって、 makeに対してロードアベレージに応じて同時に実行するジョブの数を 制限することができます。‘-l’あるいは‘--max-load’オプションに 続けて小数を例のように加えます。

 
-l 2.5

この場合、ロードアベレージが2.5を超えたときにはmakeは複数のジョブを 開始しません。また、‘-l’に数値をつけない場合は以前の‘-l’で与えた ロードの制限をなくします。

より正確にいうと、makeがジョブを開始する際にすでに少なくとも1つの ジョブが動作中だとすると、現在のロードアベレージをチェックし、‘-l’で 与えられた制限よりも小さくない場合にはmakeは、ロードアベレージが 下がるのを待つか、ほかのすべてのジョブが終了するのを待ちます。

デフォルトでは、この制限はありません。


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

5.4 コマンドのエラー

個々のシェルコマンドに戻ったあと、makeは終了ステータスを見ます。 コマンドの実行が成功している場合は次のコマンド行が新しいシェルで 実行されます。最後のコマンド行が終了するとルールが終了となります。

もしエラーが起きた場合(終了ステータスがゼロでない場合)、makeは現在 のルールを諦め、おそらくすべてのルールについても諦めます。

一定のコマンドの実行時の失敗は問題を表示しないことがあります。たとえば、 ディレクトリの存在を保証するためにmkdirコマンドを使うかもしれません。 すでにそのディレクトリが存在している場合、makeはエラーを報告しますが これを無視してほしい場合もあります。

コマンド行におけるエラーの無視をさせる場合には、‘-’を最初のタブのあとの 行の先頭に置きます。‘-’はコマンドが実行のためにシェルに渡される直前に 破棄されます。

たとえば、

 
clean:
        -rm -f *.o

このようにしておけば、削除できない場合でもrmは継続できます。

-i’または‘--ignore-errors’フラグをつけてmakeを実行した 場合、すべてのルールのすべてのコマンドのエラーが無視されます。必要条件がない 場合には、特別なターゲット.IGNOREに対するmakefileのルールは同様の 効果を持ちます。ただし、その方法は時代遅れで、‘-’のほうがより柔軟性が あります。

-i’または‘--ignore-errors’フラグによってエラーが無視される場合、 makeはステータスコードを出力する以外はエラーを無視し、成功したかの ごとく扱い、コマンドから抜け、エラーが無視されたことを示します。

makeに対して無視するように指定されなかったエラーが起きた場合には、 現在のターゲットが正しく再構成されないか、直接的あるいは間接的にほかに 依存していることを暗示しています。必要条件が達成されなければ、ターゲットに 対してのそれ以上のコマンドの実行は行なわれません。

通常、makeはこのような状況ではただちに諦め、ゼロでないステータスを 返します。しかしながら、‘-k’または‘--keep-going’フラグが 指定されている場合、makeは諦めてゼロでないステータスを返すまえに、 必要に応じて保留になっているターゲットのほかの必要条件を再構成することを 継続しようとします。たとえば、あるオブジェクトファイルのコンパイルで エラーとなったあと、make -kはリンクすることが不可能とわかっていても ほかのオブジェクトファイルのコンパイルを継続します。 See section オプションのサマリー.。

makeの通常のふるまいは、特定のターゲットをアップデートすることが 目的であると仮定しています。しかし、makeはこれが無理だとわかると ただちに失敗を表示します。‘-k’オプションによって実際の目的が可能な限り プログラムでの変更をテストできるようにすることで、次のコンパイルのまえに いくつかの独立した問題を解決できるように発見することができます。 Emacsのcompileコマンドがデフォルトで‘-k’フラグを渡すのは このような理由によります。

通常、コマンドが実行に失敗し、ターゲットファイルが変更された場合、 そのファイルは損なわれて使用されないことになります。あるいは少なくとも 完全にはアップデートされません。ファイルのタイムスタンプが アップデートすべきタイミングだと告げても、次回のmakeの実行時に アップデートは行なわれません。この状況はシグナルによってコマンドが killされた場合によく似ています (see section makeの中断あるいはkill.)。したがって、 一般的には、ファイルの変更開始後にコマンドが失敗した場合には、 ターゲットファイルを削除するのが正しい方法でしょう。 make.DELETE_ON_ERRORがターゲットになっている場合に そのように動作します。この動作はmakeに関して好ましい動作なのですが、 歴史的な互換性のため明確に指示する必要があります。


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

5.5 makeの中断あるいはkill

コマンド実行時にmakeが致命的なシグナルを受け取った場合、 コマンドによってアップデートされるはずのターゲットファイルを 削除することになります。これは、ターゲットファイルがmakeの 最初のチェックから最終更新時刻が変化している場合に行なわれます。

ターゲットの削除の目的は、次回makeが動作する際に最初から 再構成することを確認することです。これはなぜかというと、コンパイラが 動作している際にCtrl-cが押されたとします。その際、‘foo.o’が 書き始められていたとします。Ctrl-cはコンパイラをkillし、結果的に ソースファイル‘foo.c’よりも新しい最終更新時刻を持つ 不完全なファイルができてしまうことになります。しかしmakeも またCtrl-cシグナルを受けるため、この不完全なファイルを削除します。 makeがこうしなければ、次回のmakeの呼び出し時に‘foo.o’を アップデートしないことになります。その結果、半端なオブジェクトファイルの リンクを試みようとしたリンカから奇妙なエラーメッセージが 示されてしまいます。

このようなターゲットファイルの削除を特別なターゲット.PRECIOUSを 作ることで防ぐこともできます。ターゲットの再構成のまえに、make.PRECIOUSの必要条件の有無をチェックし、シグナルが発生したときに ターゲットを削除すべきかどうかを判断します。この方法を用いる場合は、 ターゲットが自動的な流れのなかでアップデートされたり、 内容によらずに修正時刻の記録のために存在したり、トラブルのソートを 防ぐためにつねに存在しなければならないなどの場合です。


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

5.6 makeの再帰的用法

makeの再帰的用法とは、makefile中のコマンドとしてmakeを 用いることです。大きなシステムを作る際のさまざまなサブシステムにmakefileを 分割したい場合にこのテクニックは有益です。たとえば、サブディレクトリ ‘subdir’があってそのなかにmakefileがあり、そのなかでmakeを 実行したい場合には以下のように記述することができます。

 
subsystem:
        cd subdir && $(MAKE)

もしくは、以下と同様です(see section オプションのサマリー.)。

 
subsystem:
        $(MAKE) -C subdir

読者はこの例をコピーしてmakeの再帰的なコマンドを書くことができます。 しかし、それらがどのように働き、サブのmakeがトップレベルの makeとどのように関連するのかなどを知っておく必要があります。

便利なように、GNUのmakeは変数CURDIRをカレントの ワーキングディレクトリのパス名にセットすることができます。-Cが 有効な場合は、オリジナルではなく新しいディレクトリのパス名を含みます。 makefileに設定された場合は、その変数の値は同じ優位性を持ちます (デフォルトでは環境変数CURDIRはそれをオーバーライドしません)。 注意しなければならないのは、この変数の設定はmakeの動作には まったく影響しないということです。


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

5.6.1 MAKE変数の働き

makeを再帰的に用いる場合は、以下のようにつねにMAKE変数を用い、 コマンド‘make’は使用しません。

 
subsystem:
        cd subdir && $(MAKE)

この変数の値はmakeが呼び出されるファイル名です。 このファイル名が‘/bin/make’である場合、実行されるコマンドは ‘cd subdir && /bin/make’です。特別なバージョンのmakeを トップレベルのmakefileで使用する場合には、その同じバージョンが再帰的に 呼び出されます。

特別な機能として、変数MAKEをルールのコマンドで使用する場合、 ‘-t’(‘--touch’)、‘-n’(‘--just-print’)あるいは ‘-q’(‘--question’)の効果を代替します。また、MAKE 変数を使用する場合、‘+’文字をコマンド行の先頭で試用する場合と 同じ効果をもたらします。 See section コマンド実行の代替.。

上記の例で、コマンドを‘make -t’とみなしてください。(‘-t’ オプションは実際には何もコマンドを実行せずにターゲットが 最新であることにします。コマンド実行の代替. を参照。)‘-t’の通常の定義に従って、例のなかの‘make -t’ コマンドは‘subsystem’という名前のファイルを作るだけでほかには 何もしません。本当に実行したいコマンドは‘cd subdir && make -t’ のはずですが、実際にはコマンドが実行されません。

この特別な仕組みは希望どおりのことをしてくれます。それは、ルールの コマンド行が変数MAKEを含んでいる場合はつねに‘-t’、‘-n’、 ‘-q’フラグはその行に適用されません。MAKEを含んでいる コマンド行は、ほとんどのコマンドが実行されないフラグの存在にかかわらず 正常に実行されます。通常のMAKEFLAGSの仕組みは、サブのmakeに フラグを渡します (see section サブのmakeへのオプションの伝達.)。 したがって、ファイルのtouchやコマンドの出力の要求はサブシステムに伝達されます。


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

5.6.2 サブのmakeへの変数の伝達

トップレベルのmakeの変数の値は、明示的な要求によって環境(変数)を 通してサブのmakeに渡されます。また、これらの変数はデフォルトで サブのmakeのなかで定義されます。しかし、‘-e’スイッチを 使用しない限り、サブのmakeのmakefileによって使用されるmakefileで 指定されるものをオーバーライドしません (see section オプションのサマリー.)。

渡された、もしくはエクスポートされた変数の値をmakeはコマンドの 実行のために環境にセットします。反対にサブのmakeは変数テーブルを その環境を初期化に用います。 See section 環境(変数)からの変数の取得.。

明確な要求による以外は、makeは環境の初期状態で定義されるか、 あるいはコマンド行でセットされる場合にだけ変数をエクスポートします。また、 その場合は文字、数字、アンダースコアだけからなる名前となります。 シェルによっては、文字、数字、アンダースコア以外の文字からなる名前には 対処できない場合があります。

SHELLという特別な変数とMAKEFILESはつねにエクスポートされます (エクスポートしないという要求がない限り)。MAKEFILESはまた必ず エクスポートされます。

makeはコマンド行で定義された変数の値をMAKEFILES変数に 置くことによって、サブのmakeに自動的に渡します。

変数は、makeによってデフォルトで作成されたものである場合は通常は 渡されません (see section 暗黙のルールで使用される変数.)。 サブのmakeはそれらの定義を自身で行ないます。

特定の変数をサブのmakeに渡したい場合は、exportディレクティブを 以下のように用います。

 
export variable

変数のエクスポートをしたくない場合には、unexportディレクティブを 以下のように用います。

 
unexport variable

変数とエクスポートを同時に行なう便利な方法もあります。

 
export variable = value

は、以下と同じ結果をもたらします。

 
variable = value
export variable

また、

 
export variable := value

は、以下と同様の結果をもたらします。

 
variable := value
export variable

同様に

 
export variable += value

は、以下とまったく同じです。

 
variable += value
export variable

See section 変数へのテキストの追加.。

ここで、makeのなかのexportunexportディレクティブは シェルshにおいて同じように働くことに気づくかもしれません。

デフォルトですべての変数をエクスポートさせる場合はexportをこのように 使用できます。

 
export

これは、makeに対してexportunexportディレクティブで 明確に言及されない変数をエクスポートさせるように指示します。 unexpotディレクティブで与えられたいかなる変数も決して エクスポートされません。一方、デフォルトでexportを用いて変数が エクスポートされる場合は、英数字とアンダースコア以外の文字をを含む名前の 変数はexportディレクティブでとくに言及しない限り エクスポートされることはありません。

exportディレクティブによって起きるふるまいは、GNUのmakeの 古いバージョンではデフォルトです。makefileがこのふるまいに依存している場合で 古いバージョンのmakeとの互換性を保ちたい場合には、特別なターゲット .EXPORT_ALL_VARIABLESexportディレクティブのかわりに 記述します。そうすると、古いmakeでは無視され、export ディレクティブはシンタックスエラーを起こします。

また、unexportを使用することで、makeがデフォルトで変数を エクスポートしないように設定することもできます。このふるまいは デフォルトなので、exportが以前に指定されている場合にのみ 必要になります。しかし、exportunexportによっていくつかの コマンドに関しては変数をエクスポートし、ほかのコマンドに対しては エクスポートしないということはできません。最後に現われたexportまたは unexportディレクティブがmakeの動作を決定します。

特殊な機能として、変数MAKELEVELは下位のレベルに渡される際に 変更されます。この変数の値は文字列で、レベルの深さを10進数で表わすものです。 値は、‘0’がトップレベルのmake、‘1’がサブのmake、 ‘2’がサブのサブのmakeというぐあいです。この数値の増加は、 コマンドに対する環境へのmakeのセットが行なわれる場合に発生します。

MAKELEVELの主な用途は、条件ディレクティブにおいてそれをテスト することです(see section Makefileの条件文.)。 この方法によって、makefileのふるまいを再帰的に動作するか、あるいは 直接的に動作するかを記述することができます。

また、すべてのサブのmakeのコマンドが付加的なmakefileを使用するように 変数MAKEFILESを使用することができます。 MAKEFILEの値は、空白で区切られたファイル名のリストで、 外部のmakefileで定義されている場合には、この変数は環境変数を通じて 渡されます。そして、事前にそれを読み込むように、サブのmakeに 対して特別なmakefileのリストを与えることになります。 See section MAKEFILESの変数.。


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

5.6.3 サブのmakeへのオプションの伝達

-s’と‘-k’フラグなどは変数MAKEFLAGSを通じてサブの makeに自動的に渡されます。この変数はmakeにより自動的に 設定され、makeが受け取ったフラグ文字になります。したがって、 ‘make -ks’を実行すると、MAKEFLAGSは‘ks’という値を 得ることになります。

結果的に、すべてのサブのmakeは自身の環境において、MAKEFLAGSに 対する値を得ることになります。そして、あたかも引数を与えられたかのように 値とプロセスからフラグを得ることになります。 See section オプションのサマリー.。

また、コマンド行で定義された変数はMAKEFLAGSを通じてサブの makeに渡されます。‘=’を含むMAKEFLAGSの値は、あたかも コマンド行で現われたかのようにmakeが変数定義として扱います。 See section 変数のオーバーライド.。

オプション‘-C’、‘-f’、‘-o’と‘-W’はMAKEFLAGSに 渡されず、下位のレベルにも渡されません。

-j’オプションは特別なケースです(see section パラレル実行.)。 なんらかの数値‘N’を設定して、OSがそれをサポートしている場合 (大部分のUnixがそうですが、それ以外はそうではありません)、親にあたる makeとすべてのサブのmakeは‘N’個のジョブだけが同時に 動作するのを保証するように伝達します。注意すべきことは、再帰的にマークされた (see section コマンド実行の代替.) いかなるジョブもトータルなジョブの数にはカウント されないことです。(いいかえれば、‘N’個のサブのmakeだけが動作し、 実際のworkのためのスロットも残されていない状態になるということです。)

読者のOSが上記のような伝達をサポートしていない場合、指定した値のかわりに、 MAKEFLAGSに対して‘-j 1’がつねに渡されます。このことは、 ‘-j’オプションがサブのmakeに渡される理由で、パラレルに 実行される要求よりも多くのジョブを得られます。数字なしで‘-j’を 与えた場合、可能な限り多くのジョブがパラレルに動作し、下位に伝達されます。

もし、ほかのフラグを下位に伝達したくない場合には、MAKEFLAGSの値を 以下のように変更します。

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

コマンド行の変数定義は実際にはMAKEOVERRIDES変数において現われます。 またMAKEFLAGSはこの変数への参照を含みます。通常のように下位への 伝達を望む場合で、コマンド行の変数定義の伝達は望まない場合は、以下のように 記述します。

 
MAKEOVERRIDES =

この方法はつねに有益であるとは限りませんが、システムによっては環境変数の サイズに制限があり小さすぎる場合があり、MAKEFILの値を代入する際に そのサイズを越える場合があります。‘Arg list too long’という エラーメッセージが表示された場合はこの問題です。 (POSIX.2に対しての厳格な準拠のため、MAKEOVERRIDESは特定のターゲット ‘.POSIX’がmakefileに現われる場合にはMAKEFLAGSに影響を 与えませんので気にする必要はありません。)

歴史的な互換性のために、同様な変数MFLAGSもあります。この変数は コマンド行の変数定義を含まないことを除けば、MAKEFLAGSと同じ値を持ち、 空でない限りつねにハイフンで始まります(‘--warn-undefined-variables’の ように複数文字のバージョンのオプションで始まる場合だけは ハイフンで始まります)。

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

しかし、現在のMAKEFLAGSではこの使用法は冗長です。makefileを古い makeプログラムと互換性を保つ場合にこの方法を使用してください。 そうしておけば、現在のmakeと同様にうまく動作するでしょう。

-k’のようなオプション(see section オプションのサマリー.) を使用しmakeを実行するごとにセットしようとする場合には、 MAKEFLAGS変数もまた有益です。使用法は環境設定のなかで MAKEFLAGSに値をセットするだけで、makefileに対して効果のあるように 付加的なフラグを指定します。(注意すべきことは、この方法ではMFLAGSは 使用できないことです。この変数は互換性のためだけにあり、makeは その値を解釈しません。)

makeMAKEFLAGSの値を解釈する際(環境変数またはmakefileから) には、値の前にあるハイフンから行なわれます。そして、空白によって値を区切り、 それらをコマンド行のオプションのように解釈していきます(ただし、 ‘-C’、‘-f’、‘-h’、‘-o’、‘-W’とその ロングネームバージョンは無視されますし、不正な値に対してエラーを 返しません)。

MAKEFLAGSを環境設定に入れる場合は、makeの動作に影響を 与えたりmakefileの目標などに影響を与えるオプションが含まれていないことを 確認する必要があります。たとえば、‘-t’、‘-n’や‘-q’オプションが 含まれている場合、よくない結果が待っていて、悩みの種に なってしまうことでしょう。


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

5.6.4 ‘--print-directory’オプション

いくつかのレベルのmakeの再帰的呼び出しを行なう場合、‘-w’あるいは ‘--print-directory’オプションはmakeが処理を開始し終了する それぞれのディレクトリの表示を簡単にすることができます。たとえば、 ‘make -w’がディレクトリ‘/u/gnu/make’で実行される場合、 makeは次の書式で表示させることができます。

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

なにかを実行するまえにこのように記述し、終了したあとのために以下の ように1行記述しておきます。

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

通常は、このオプションを指定する必要がありません。なぜなら、‘-C’を 使用すると自動的に‘-w’がオンになり、サブのmakeでも そうだからです。しかし、メッセージを出さない‘-s’オプションを つけた場合、あるいは‘--no-print-directory’を明確に指示した場合には、 makeは‘-w’を自動的にオンにはしません。


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

5.7 コマンドの組み合わせの定義

さまざまなターゲットを作る際にコマンドの同じシーケンスが有用な場合、 defineディレクティブによって決まったシーケンスとして定義することが でき、ターゲットのルールからそのシーケンスを参照することがも可能になります。 このシーケンスは実際には変数のため、ほかの変数名と矛盾しないようにしなければ なりません。

ここにコマンドのシーケンスの定義の例があります。

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

ここで、run-yaccは定義する変数名で、endefは定義の終わりを 示します。この2つのあいだの行がコマンドになります。define ディレクティブは参照する変数を展開せず、シーケンスにおいて ファンクションコールも行ないません。‘$’文字、括弧、変数名などは 定義する変数の値の一部となります。 defineの完全な説明については、 See section 変数のまったく同一の定義.。

この例の最初のコマンドは、ルールがコマンドシーケンスを使用することに かかわらず、最初の必要条件としてYaccの実行を行ないます。Yaccからの 出力ファイルは‘y.tab.c’となります。2番目のコマンドはその出力を ルールのターゲットファイル名に変更します。

コマンドのシーケンスを使用するためには、ルールのコマンドに変数を代入します。 そして何かほかの変数(see section 変数参照の基礎.) のように代用します。defineで定義された変数は再帰的に変数に 展開されるため、defineで記述された変数の参照は展開されます。 たとえば、

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

foo.y’は、run-yaccの値や‘$@’に対する‘foo.c’に 存在するときは変数‘$^’に対して代用されます。

これは実例ですが、このような特殊なものは実際にはありません。なぜならば、 makeはファイル名に基づくコマンドのこのような役割を暗黙の ルールとして持っているからです (see section 暗黙のルールの使用.)。

コマンドの実行に際しては、それぞれのコマンドのシーケンスは、ルールのなかで 独自に現われたかのようにタブが先頭についた形で扱われます。そして、 makeはそれぞれの行で独立したサブシェルを呼び出します。また、 コマンド行に影響を与える特別なプレフィックス文字(‘@’、‘-’と ‘+’)をそれぞれのコマンドシーケンスで用いることができます。 See section ルールのなかでのコマンドの書き方.。 以下は、このようなコマンドシーケンスの例です。

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

makeは最初の行すなわちechoコマンドをエコーしませんが、 次の2つのコマンド行はエコーします

一方、シーケンスへの参照に用いられるコマンドのプレフィックス文字は シーケンスのすべての行に適用されるため、ルールは、以下のようになります。

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

このように一切エコーしません。(‘@’の詳しい説明については、 See section コマンドエコー.。)


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

5.8 空のコマンドの使用

何もしないコマンドを定義することが有用な場合があります。この場合、 以下のように単純に空白からなるコマンドを与えるだけでいいのです。

 
target: ;

target’に対して空白のコマンドを与えます。または、タブ文字から始まる 空のコマンド文字列を使用することもできますが、見かけ上、何もない状態に なりますので混乱することがあります。

何もしないコマンドを定義する理由は何でしょうか。その唯一の理由は、 ターゲットが暗黙のコマンド(暗黙のルールから、あるいは.DEFAULTの 特別なターゲットから)を得てしまうことを防ぐ意味です。.DEFAULTの 特別なターゲットについては暗黙のルールの使用.、 最後の手段のルールの定義.を参照してください。

現実のファイルではないターゲットに対して空のコマンド文字列を定義しようと 考えても、実際には必要条件の再構成が可能なようにできるだけです。しかしながら、 この方法はベストとはいえません。なぜなら、ターゲットファイルが実際に 存在する場合には必要条件が適切に再構成できなくなるからです。 よりよい方法については、See section 偽のターゲット.。


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

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