1

lex yacc プロジェクトをコンパイルするための非常に基本的な Makefile の例があります。

all: y.tab.o lex.yy.o

lex.yy.c: calc.l
    #flex calc.l

y.tab.c y.tab.h: calc.y
    #bison -d calc.y

lex.yy.o: lex.yy.c y.tab.h
    #gcc -c lex.yy.c

y.tab.o: y.tab.c
    #gcc -c y.tab.c

しかし、make を実行すると、bison が 2 回呼び出されていることがわかります。ターゲット y.tab.c と y.tab.h ごとに 1 回と仮定しています。

#bison -d calc.y
#gcc -c y.tab.c
#flex calc.l
#bison -d calc.y
#gcc -c lex.yy.c

これは、並列ビルドで問題を引き起こしています。依存関係が上記と同じになるようにメイクファイルを変更するにはどうすればよいですか。ただし、bison は 1 回だけ呼び出されて、両方のターゲット ファイルを生成します。

4

4 に答える 4

1

このジレンマに対する最善の答えは、少なくとも GNU make を使用している場合は、パターン ルールを使用することです。y.tab.cこれは、出力とy.tab.h;を呼び出すことができないことを意味します。出力名は入力名の派生物である必要があります。とを生成しcalc.yたいとします。次に、次のように記述します。calc.tab.ccalc.tab.h

%.tab.c %.tab.h: %.y
        bison $<

all: calc.tab.o

複数のターゲットを持つパターン ルールはまさにあなたが望むことを行います: それらは GNU make に、ルールの 1 回の呼び出しで両方のターゲットを構築するように指示します。これにより、並列ビルドが必要なく適切に機能することが保証されます.NOTPARALLEL

于 2013-11-06T13:09:39.563 に答える
0

あなたの問題は、y.tab.c y.tab.h: calc.yマルチターゲットルールのように見える行です。しかし実際には、これは 2 つの個別のルールの省略形です。従来の make はファイルがどこから来るかについてずさんなので、これで十分うまくいくことがよくあります。しかし、Virgile が指摘したように、並行するケースではそうではないかもしれません。

これを実際にマルチターゲット ルールとして扱うmakeppを使用すると、この問題は発生しません。また、makepp は誰が何をビルドしたかについて非常に正確です (タイムスタンプにだまされるのではなく、将来のビルドのためにそれを追跡するため)。それが、約束された信頼性を提供できる唯一の方法です。

于 2013-11-06T11:04:58.603 に答える