GNU Makefile におけるプロセス置換

GNU Makefile におけるプロセス置換

bash プロンプトでは、疑似ファイルを使用して diff を実行できます。

diff <(echo test) <(echo test)

これをそのまま Makefile に追加すると失敗します。

all:
        diff <(echo test) <(echo test)

エラー (ヒント: このシステムでは /bin/sh は /bin/bash を指します):

/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `diff <(echo test) <(echo test)'

これはどういう意味ですか? また、一時ファイルを使用せずに 2 つの出力を比較する方法はありますか?

答え1

/bin/shbashはシステム上に存在している可能性がありますが、 として呼び出されるとshbashは POSIX モードで実行されます (POSIXLY_CORRECTが定義されているか、 で起動された場合と同様--posix)。

このモードでは、プロセスの置換は存在しません。

解決策:

  1. 明示的な一時ファイルを使用する:

    all:
        command1 >tmpfile
        command2 | diff tmpfile -
        rm -f tmpfile
    
  2. bash -cインライン スクリプトを使用します。

    all:
        bash -c 'diff <(command1) <(command2)'
    
  3. Makefile 変数をSHELL次のように定義します (またはシステム上の/bin/bashパスを指定します)。bash

    SHELL=/bin/bash
    

移植性が必要な場合は、最初のソリューションを選択してください。 への依存関係が問題ない場合はbash、2 番目のソリューションを選択してください。さらに、GNU 以外の実装を気にする必要がない場合はmake、3 番目のソリューションを使用してください。


設定についてSHELL: POSIX 標準では、Makefile 内の実行ファイルは、system()C ライブラリ関数を使用してで呼び出す必要があるとされていますmake。この関数は、環境変数を使用することが保証されていませんSHELL(実際、標準では使用が推奨されていません)。標準では、Makefile 変数の設定が、SHELL環境変数 SHELLただし、私が知る限りのほとんどの実装では、コマンドを実行するためにmakeMakefile 変数が使用されます。SHELL

の提案makeユーティリティの根拠使用するにはbash -c

歴史的なMAKESHELL機能、および他の実装によって提供される関連機能はmake省略されました。一部の実装では、makeコマンドを実行するために使用するシェルをユーザーがオーバーライドできるようにするためにこの機能が使用されています。これは混乱を招きました。ポータブル の場合make、シェルは makefile ライターによって選択される必要があります。さらに、makefile ライターは代替シェルの使用を要求しながら、makefile をポータブルと見なすことはできません。代替シェルを指定するためのメカニズムを標準化することは可能ですが、既存の実装ではそのようなメカニズムについて合意されておらず、makefile ライターはターゲットのルールでシェル名を指定して代替シェルを呼び出すことができます。たとえば、次のようになります。

python -c "foo"

関連情報