1

C++ makefile で奇妙な問題が発生しています。使っていた古いものは自殺したくなったので、今日の午後に書き直しました。変数の再割り当てと動的依存関係に関する奇妙な問題に直面しています。

この質問の目的のために、次の値を想定します。

OBJMOD_MODULENAME = obj/lib/foo.o obj/lib/bar.o obj/lib/quux.o
LIBDIR         = lib/
CXX            = g++
CXXLIBLINK     = -shared
LIB            = -lm -lpt

次の形式のターゲットがあります。

modulename: OBJ_CURRENTMOD = $(OBJMOD_MODULENAME)
modulename: $(OBJMOD_MODULENAME) lib/metrics.so

その後、次の別の形式:

$(LIBDIR)%.so: $(OBJ_CURRENTMOD)
    $(CXX) $(CXXLIBLINK) -o $@ $(OBJ_CURRENTMOD) $(LIB)

コード ブロック内の行は、常にコード ブロック内に表示されている順序で表示されますが、デバッグの過程でブロックの相対的な位置を変更しました。

この問題は、ソース ファイルを変更して「make modulename」で再コンパイルしようとすると発生します。オブジェクト ファイルの構築は期待どおりに機能しますが、ファイルが既に存在する場合、ライブラリの再構築は行われません。つまり、 で指定された依存関係$(OBJ_CURRENTMOD)は無視されます。$(OBJMOD_MODULENAME)ライブラリの依存関係で使用すると、期待どおりに機能します。の値が$(OBJ_CURRENTMOD)期待どおりであることをさまざまな方法で確認しました(たとえば、ライブラリターゲットの最初の行に固執echo $(OBJ_CURRENTMOD)します)が、何を試しても、再コンパイルをトリガーするのに間に合うように変数が更新されないようです依存関係のチェックに。

これを入力していると、回避策が見つかりました。

OBJMOD_MODULENAME = obj/lib/foo.o obj/lib/bar.o obj/lib/quux.o
LIBDIR         = lib/
CXX            = g++
CXXLIBLINK     = -shared
LIB            = -lm -lpt

modulename: OBJ_CURRENTMOD = $(OBJMOD_MODULENAME)
modulename: $(OBJMOD_MODULENAME) lib/metrics.so

$(LIBDIR)%.so: herp $(OBJ_CURRENTMOD)
    $(CXX) $(CXXLIBLINK) -o $@ $(OBJ_CURRENTMOD) $(LIB)

herp: $(OBJ_CURRENTMOD)

このダミーターゲットは、変数参照が強制的に更新され、私の問題を解決する前に追加されました。これはmakeのバグか何かですか?make --version は GNU make 3.81 を示します。他の誰かがこの奇妙な動作を確認できますか? 私はひどく愚かなことをしているだけですか?私は何時間もそれを見つめていましたが、それほど驚かないでしょう。

編集:実際には修正されていないことが判明しました。必要かどうかに関係なく、毎回実行するようにトラップしていました。

変更された値を確認するには:

$(LIBDIR)%.so: $(OBJ_CURRENTMOD)
    echo $(OBJ_CURRENTMOD)
    $(CXX) $(CXXLIBLINK) -o $@ $(OBJ_CURRENTMOD) $(LIB)
4

2 に答える 2

1

ルールの前提条件リストでターゲット固有の変数値 を使用しています。これは許可されていません。ターゲット固有の変数は、ターゲットのレシピでのみ使用できます。OBJ_CURRENTMOD$(LIBDIR)%.so

別の問題は、変数を定義していて、後で割り当てられていないOBJ_MODULENAME別の variable にアクセスすることです。$(OBJMOD_MODULENAME)

于 2012-06-18T08:17:55.570 に答える
1

$(LIBDIR)%.soコメントの 1 つで述べたように、パターンが の前提条件とどのように一致するかはわかりませんが、が意図されているとmodulename仮定すると、 を構築するために使用されます。metrics.solib/metrics.solib/metrics.so

interjay が指摘したように、「自動変数と同様に、これらの値はターゲットのレシピ (および他のターゲット固有の割り当て) のコンテキスト内でのみ使用できます。」それらは、ターゲット パターンまたは pre のリストでは使用できません。 -requisites の前提条件の 1 つが変更されたときにターゲットが再構築されない理由を説明し$(OBJ_MODULENAME)ます。

前提条件リストで有効にするには、二次拡張$(OBJ_CURRENTMOD)を使用する必要があります

.SECONDEXPANSION: 
$(LIBDIR)%.so: $ $(OBJ_CURRENTMOD)
        $(CXX) $(CXXLIBLINK) -o $@ $(OBJ_CURRENTMOD) $(LIB)
于 2012-06-18T15:54:08.760 に答える