web-dev-qa-db-ja.com

Makefileと.ONESHELL

いつ .ONESHELLは使用されません。Makefileは、各シェルコマンドを個別のシェルで実行します。これの利点は何ですか? makefileが同じシェルを使用しないのはなぜですか?

4
Nikhil

1つの理由は、レシピコマンドの1つでの失敗がGNU makeによって検出されないことです。シェルの最終的な終了ステータスのみがmake.SHELLFLAGS-eにさらに設定して、エラー時にシェルを早期に終了させる必要があります(これは、.ONESHELLがなくても、マルチコマンドシェルの呼び出しで必要です need 最初のエラーで失敗する)。

これは、ShellがPOSIXシェルである場合に適しています。 MakefileはShellをたとえばに設定することもできます。 /usr/bin/Perlまたはその他のコマンドインタープリタ。次に、.ONESHELLを使用することが適切かどうかは不明です。

.ONESHELLmakeのデフォルトの動作にすると、古いMakefileが壊れる可能性があります。

これはPOSIX標準またはGNU makeによるその標準への準拠に関する質問ではありませんが、 make は、当面の問題についてこれを述べています:

makeの一部の拡張バージョンのデフォルトでは、ターゲットのすべてのコマンドラインをグループ化し、単一のシェル呼び出しを使用してそれらを実行します。 System Vの方法では、各行を個別のシェルに個別に渡します。シングルシェル方式には、パフォーマンスの点で有利であり、多くの継続的なラインに対する要件がありません。ただし、この新しいメソッドに変換すると、多くの従来のメイクファイルで移植性の問題が発生します。したがって、POSIXメイクファイルの動作は、System Vの動作と同じになるように指定されています。特別なターゲット.ONESHELLを実装拡張として使用して、ターゲットまたはターゲットのグループの単一シェルグループ化を実現することをお勧めします。

GNU makeは、System Vの動作を実装しているため、この点でPOSIXに準拠していますおよびは、必要に応じて代替動作を有効にする.ONESHELLターゲットを提供します。 ... GNU makeが現在の動作を維持するもう1つの理由です。

9
Kusalananda

.ONESHELLは、GNU移植性がなく、POSIX標準の一部ではないベンダー固有の拡張機能です。

これがPOSIX標準にない理由は、これをサポートする実装が今のところ1つしかないためです。

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

POSIXは既存の動作を標準化しようとしますが、POSIXは既存のオリジナルのUNIX実装を標準と矛盾させたくありません-特定の動作が明確な設計バグとして見られる場合を除きます。

1977年のスチュアートフェルドマンによる元のmake実装は、sh -ce cmdlineを使用して別のシェルのアクションリストの各行を呼び出し、これがすべての以降のmake実装のマスターになりました。

ただし、.ONESHELLが有効な場合、GNU実装(個別に表示)でも問題はありません。GNU makeは、コマンドを呼び出すときのシェルの-eフラグこれにより、.ONESHELLが原因で発生する複数行のシェルスクリプトがエラー発生時に終了しなくなります。

それ以外の場合、.ONESHELLにはいくつかのメリットがあります。

  • 複数行のシェルスクリプトは、メイクファイル内のバックスラッシュ改行シーケンスによってmake内で使用できます。

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

  • 私のsmake実装は、echoコマンドのインラインサポートも実装しています。これは、行の最初のコマンドがechoで、セミコロンが1つだけで、その他の単純なコマンドが続く場合です。これにより、すべてのケースの90%以上にわたってシェルを呼び出す必要がなくなります。

3
schily