重複の可能性:
別のプロセスにパイプされた終了コードを取得する
私は、次のコマンドライン(makefileから)を使用して、人間が読める内容に減らすPerlスクリプトを介してコンパイラの詳細なエラーメッセージを渡します。
g++ -c source.cpp -o source.o 2>&1 | perl /bin/gSTLFilt.pl
残念ながら、このアプローチはコマンドから返されたエラー値を「マスク」しますg++
。 makeはコマンドのエラー結果g++
のみを返すので、コマンドが失敗したことを知りません。perl
出力をパイプして元のエラー状態を維持する方法はありますか?
違いがある場合:私はGNU bashバージョン2.04.0(1)-リリース(i686-pc-)を実行しているMSYSコンソールでGNU Make 3.81とg ++(GCC)3.4.5(mingw-vistaspecial r3)を使用しています。 msys)(Windows XP)。
答え1
sh.exe
Windows実行可能ファイルにその名前を使用する複数のシェルがあるため、シェルが何を提供しているのかわかりませんが、bash
似ているか似ている場合は配列を使用できます$PIPESTATUS
。あなたの例は次のようにすることができます:
g++ -c source.cpp -o source.o 2>&1 | perl /bin/gSTLFilt.pl
echo "${PIPESTATUS[0]}"
答え2
Bashには次のオプションがありますpipefail
。
The return status of a pipeline is the exit status of the last command,
unless the pipefail option is enabled. If pipefail is enabled, the
pipeline's return status is the value of the last (rightmost) command
to exit with a non-zero status, or zero if all commands exit success-
fully.
だから:
set -o pipefail && $GCC_COMMAND | $PERL_COMMAND
Makeは各行に対してサブシェルの各行を実行します。したがって、gcc行の先頭に追加する必要があります。 set を使って make に 1 つのコマンドだけを実行させる方法があるかもしれませんが、pipefail
よく分かりません。
SHELL=/bin/bash
(クリエイターはこれを使用する必要があります)
または、次のことを試してください。
bash -o pipefail -c "$GCC_COMMAND | $PERL_COMMAND"
答え3
既存のシェルでは、パイプラインの最初のコマンド状態はスクリプトにまったく報告されません。では、最後のコマンドの状態のみを使用できます$?
。
バッシュ≥3.0では、パイプラインのどこでもエラーが発生した場合は、停止したい場合にこのpipefail
オプションを使用してください。。
g++ -c source.cpp -o source.o 2>&1 | perl /bin/gSTLFilt.pl
より一般的には、Bashでは、配列はPIPESTATUS
最後の$?
パイプラインのすべてのコマンドを含むように一般化されています。
$ (exit 1) | (exit 2) | (exit 3); echo ${PIPESTATUS[@]}
1 2 3
Zshにも同じ機能がありますが、配列を呼び出しますpipestatus
。
% zsh -c '(exit 1) | (exit 2) | (exit 3); echo $pipestatus'
1 2 3
bash(IIRCはmsysが提供するシェル)を使用したい場合はsh
それを使用できますPIPESTATUS
。そうでない場合は、終了状態を最上位シェルにパイプし、フィルタプログラムを終了させることができます。入力の最後の行を読み取り、通常の入力として使用する代わりに終了するステータスを取得します。あいまいですが便利です。
メイクファイルでは、コンパイラメッセージが別の中間ファイルとして扱われる一時ファイルを使用するのが比較的一般的です。
%.otmp %.g++-log: %.cpp
g++ -c $< -o $@tmp 2>&1 >$*.g++-log
%.o: %.otmp %.g++-log
perl /bin/gSTLFilt.pl <$*.g++-log
mv $*.otmp $@