2009-03-12 12 views
7

最近、メイクベースのビルドプロセスの依存関係について.dファイルを扱う方法についていくつかの議論があります。ビルドが中断されたときに.dファイルが破損することがあるという問題が提起されました。エラー時に追加のファイルを削除するには

私たちは.DELET_ON_ERRORターゲットを使用して、ビルドが中断されるか失敗すると、生成中のオブジェクトファイルが確実に削除されるようにします。しかし、コンパイル時に.dファイルを生成するためにGCCも使用していますが、これも削除する必要があります。これについてmakeに伝える簡単な方法はないようです。

エラーが発生した場合、私たちのオブジェクトと依存ファイルの両方を削除する方法がありますか? .dファイルと.oファイルの両方が同時に生成され、エラーがあれば削除する必要があることがわかるように、ルールを設定できる方法はありますか?

代わりに、破損した.dファイルの問題を解決するために何かできることはありますか?これらの行に沿った1つの提案は、.dファイルを一時的な名前で生成し、それを正しい名前にコピーするファイルごとに別々のポストコンパイルステップを持つことです。

答えて

6

一般に、GNU makeは複数の出力を持つターゲットをサポートしていません。しかし、そのルールには例外があります:パターンルール。 makefileがパターンルールを使用してオブジェクトファイルを生成するようにメイクファイルを構造化することができれば、目標を達成することができます。たとえば:「エラー」がルールで検出されたときは、このメイクファイルとそれを見ることができます

.DELETE_ON_ERROR: 

all: foo.o 

%.o %.d: %.c 
    @touch $*.d 
    @touch $*.o 
    @exit 1 

、.Dと.oファイルの両方が削除されます。このアプローチの利点は、.dファイルの生成方法とそれを生成するルールを記述することで、依存関係グラフをより正確に表現できることです。

この場合の一般的なパラダイムは、あなたが提案したのと同じです.GCCで.dファイルを一時ファイル名に生成し、GCCコマンドが正常に完了した後にその場所に移動するようにしてください。通常、これは、シェルのトリックで達成される:ここでは「魔法」のトリック

all: foo.o 

%.o: %.c 
    gcc -o [email protected] -MMD -MF $(basename [email protected]).d.tmp -c $< \ 
     && mv $(basename [email protected]).d.tmp $(basename [email protected]).d 

、コンパイルの副作用として依存関係ファイルを生成GCCフラグ-MMDの使用である、と-MFました依存ファイルの出力名を指定できます。シェルcmd1 && cmd2の構文を使用すると、cmd1が正常に終了した場合にシェルはcmd2のみを実行します。

+0

メイクファイルの先頭にある '.DELET_ON_ERROR:'は私のすべての一時ファイルを取り除きます。ありがとう! –

+0

パターンルール "%.o:%.c"のレシピに2行目としてmvを入れることをお勧めします。シェルの '&&'を使って最初の行に置くと、動作や変更に何ら変化は見られません。 –

+0

@RichardPerrin gmakeが '-i'(エラーを無視する)オプションで呼び出されると、あなたの提案は誤った動作をします。その場合、あなたのバージョンは 'gcc'にエラーがあるかどうかにかかわらず' mv'コマンドを実行しますが、私のオリジナルはそうしません。 –

-1

私はどちらもEricの例が正しく動作していません。 GCC(バージョン4.4)は、-MMスイッチを渡すときに何もコンパイルしないので、一度に.dをコンパイルして書き込むことはできません。ここに私がやったことだ:

%.o: %.c 
    @rm -f [email protected] $(patsubst %.o,%.d,[email protected]) 
    gcc -c $< -o [email protected] 
    @$(CXX) -MM -MG > $(patsubst %.o,%.d,[email protected]) 

それは2番目のコマンド、実際のコンパイル手順は、(エリックの& &トリックを成功した場合、新しいものを生成し、三行目のみ実行され、既存.Dファイルを削除してからスタートこれは自動的に行います)。 何らかの理由で私は理解できません。既存の.oファイルは、コンパイルが失敗した場合に自動的に削除されませんが、[email protected]を最初のrmに追加すれば簡単に解決できます。

+0

'-MM'だけを指定した場合、gccは実際にファイルをコンパイルしません。私の元の答えに記述されているように、 '-MF'も使わなければなりません。 –

+0

@エリック私も-MFスイッチを追加しましたが、プリプロセッサはgccのコンパイラ部分に出力を送信していないようですので、ゼロバイトのオブジェクトファイルになります... – Wim

+0

申し訳ありません、私は間違いを犯しました。 '-MM'ではなく' -MMD'を望みます。元の回答も修正しました。 –

関連する問題