Makefileと.ONESHELL

Makefileと.ONESHELL

使用しない場合、.ONESHELLMakefileは別のシェルで各シェルコマンドを実行します。これにはどのような利点がありますか? makefileが同じシェルを使用しないのはなぜですか?

答え1

単一のシェルインスタンスでレシートに関連するすべてのコマンドを実行しない1つの理由は、コマンドの1つの失敗を検出できないためですmake。には、シェルの最終終了状態のみが付与されます。エラーが発生した場合は、シェルが早期に終了するようにmakeさらに設定する必要があります。 (これはマルチコマンドシェル呼び出しに必要であり、存在しなくても必要です。).SHELLFLAGS-e.ONESHELL必要最初のエラーでは失敗します)。

SHELLPOSIXシェルの場合はすべて大丈夫です。 Makefileは、SHELL例えば、/usr/bin/perlまたは/usr/bin/python他のコマンドソルバーとして設定することもできます。もしそうなら、その使用は適切かもしれませんし、適切ではないかもしれません.ONESHELL

.ONESHELLデフォルトの動作に切り替えると、make古いMakefileが破損する可能性があります。

これはPOSIX規格やGNUの規格への準拠に関する問題ではありませんがmakePOSIX仕様make現在の問題の内容は次のとおりです。

一部の高度なバージョンのデフォルトmakeは、ターゲットに対するすべてのコマンドラインをグループ化し、単一のシェル呼び出しを使用して実行することです。System V アプローチは、各ラインを個別に別々のシェルに渡すことです。。単一のシェルアプローチは性能上の利点を有し、多数の連続ラインを必要としない。しかし、この新しいアプローチに切り替えると、多くの歴史的なmakefileで移植性の問題が発生しました。したがって、POSIX makefile の動作は System V と同じように指定されます。.ONESHELLターゲットまたはターゲットセットの単一のシェルグループを実装するには、実装拡張として特別なターゲットを使用することをお勧めします。

GNU はmakeSystem V の動作を実装しているため、この点で POSIX に準拠しています。そして必要に応じて.ONESHELL代替動作を有効にするターゲットを提供してください。 ...これがmakeGNUが現在の動作を維持するもう一つの理由です。

答え2

.ONESHELLこれはGNUベンダー固有の拡張であり、移植性がなく、POSIX標準の一部でもありません。

これがPOSIX規格にない理由は、これまで1つの実装だけがそれをサポートしている可能性が高いです。

これが標準のデフォルトではない理由は、説明する方が簡単です。

POSIX は既存の動作を標準化しようとしますが、POSIX は、特定の動作が明白な設計エラーと見なされない限り、既存の基本 UNIX 実装が標準と競合することを好みません。

1977年、Stuart Feldmanの元の実装では、makeタスクリストの各行を別々のシェルとして呼び出しました。sh -ce cmdlineこれは、以降のすべての実装で基本となりましたmake

.ONESHELLしかし、GNU実装(別途参照)も適用には問題がないわけではありません。その理由は、GNU makeが-eコマンドを呼び出すときにシェルフラグを設定しないためです。これにより、エラーが発生したときに複数行のシェルスクリプトが.ONESHELL終了しません。

それ以外にはあまりメリットはないようです.ONESHELL

  • makeマルチラインシェルスクリプトは、makeファイルのバックスラッシュ改行シーケンスを通じて内部的に使用できます。

  • make最新の実装では、コマンドラインにシェル固有のメタ文字が含まれていない場合はシェル呼び出しを回避しようとするため、パフォーマンスパラメータは最新の実装には適用されません。

  • 私の実装では、このコマンドが1行の最初のコマンドであり、その後にセミコロンと単純な他のコマンドが続く場合に備えて、このコマンドのインラインサポートもsmake実装しました。これにより、90%以上の場合にシェルを呼び出す必要がなくなります。echoecho

関連情報