使用しない場合、.ONESHELL
Makefileは別のシェルで各シェルコマンドを実行します。これにはどのような利点がありますか? makefileが同じシェルを使用しないのはなぜですか?
答え1
単一のシェルインスタンスでレシートに関連するすべてのコマンドを実行しない1つの理由は、コマンドの1つの失敗を検出できないためですmake
。には、シェルの最終終了状態のみが付与されます。エラーが発生した場合は、シェルが早期に終了するようにmake
さらに設定する必要があります。 (これはマルチコマンドシェル呼び出しに必要であり、存在しなくても必要です。).SHELLFLAGS
-e
.ONESHELL
必要最初のエラーでは失敗します)。
SHELL
POSIXシェルの場合はすべて大丈夫です。 Makefileは、SHELL
例えば、/usr/bin/perl
または/usr/bin/python
他のコマンドソルバーとして設定することもできます。もしそうなら、その使用は適切かもしれませんし、適切ではないかもしれません.ONESHELL
。
.ONESHELL
デフォルトの動作に切り替えると、make
古いMakefileが破損する可能性があります。
これはPOSIX規格やGNUの規格への準拠に関する問題ではありませんがmake
、POSIX仕様make
現在の問題の内容は次のとおりです。
一部の高度なバージョンのデフォルト
make
は、ターゲットに対するすべてのコマンドラインをグループ化し、単一のシェル呼び出しを使用して実行することです。System V アプローチは、各ラインを個別に別々のシェルに渡すことです。。単一のシェルアプローチは性能上の利点を有し、多数の連続ラインを必要としない。しかし、この新しいアプローチに切り替えると、多くの歴史的なmakefileで移植性の問題が発生しました。したがって、POSIX makefile の動作は System V と同じように指定されます。。.ONESHELL
ターゲットまたはターゲットセットの単一のシェルグループを実装するには、実装拡張として特別なターゲットを使用することをお勧めします。
GNU はmake
System V の動作を実装しているため、この点で POSIX に準拠しています。そして必要に応じて.ONESHELL
代替動作を有効にするターゲットを提供してください。 ...これがmake
GNUが現在の動作を維持するもう一つの理由です。
答え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%以上の場合にシェルを呼び出す必要がなくなります。echo
echo