ターゲット固有の make 変数

ターゲット固有の make 変数

ターゲット固有の変数を強制的にすぐに設定する方法(ライン2)?私が望む結果はmaketoreleasemake debugto beですdebug

X = release
debug: X = debug
debug: all

# the rest is included from an external file; cannot be changed
Y := $(X)
BUILD := $(Y)

all:
    @echo $(BUILD)

答え1

問題は、GNUMakeがファイルを解析する方法が原因で発生します。

GNU makeは2つの異なるステップで動作します。最初のステップでは、すべてのメイクファイル、埋め込みメイクファイルなどを読み取り、すべての変数とその値、暗黙的および明示的なルールを内部化し、すべてのターゲットと前提条件の依存関係グラフを作成します。 2番目のステップでは、makeはこれらの内部構造を使用して再構築する必要があるターゲットを決定し、それを実行するために必要なルールを呼び出します。

メイクファイルを読む

make debug依存関係を実行すると、all:実行したかのように値が印刷されるように見えますmake all。あなたがしなければならないことは、両方allともdebug同じ依存関係をトリガするようにmakefileを変更することです。通常、次の内容が表示されます。

all: $(executable)
debug: $(executable)
$(executable): $(objs)
    <compile objects to executable>

debug決して実行されませんが、allどちらの場合も実行可能ファイルをコンパイルします。

あなたのコードは次のとおりです。

X = release

debug: X = debug

Y = $(X)
BUILD = $(Y)

.PHONY: print
print:
        @echo $(BUILD)

all: print
debug: print

作成される実際のオブジェクトではないため、偽の依存関係を印刷する必要がありました。それ以外の場合は両方がdebug必要ですallが、設定したフラグによって異なるコンパイルの依存関係になります。

答え2

YそしてBUILD変数は単純拡張変数:=(代わりに=)を使用して割り当てられます。次を参照してください。手動より多くの情報を知りたいです。デフォルトでは、変数に値が割り当てられます。変数が定義されると、これはあなたがしたいことをするのを妨げます。

ただし、ターゲット固有の変数はグローバル変数よりも優先される必要があるため、オーバーライドするとターゲットBUILD範囲内のグローバル変数が非表示になるために機能します。BUILDdebug:all:

X = release
debug: BUILD = debug
debug: all

Y := $(X)
BUILD := $(Y)

all:
    @echo $(BUILD)

converseを使用すると、それ自体は拡張変数にすぎず、debug: Y = debug機能しません。BUILD

なぜこれがうまくdebug: X := debugいかないのか正確には理解できません。ところで、ターゲット固有の変数は、グローバル単純拡張変数の後に解決されたようです。これは、ターゲット固有のBUILD変数が私のソリューションでグローバル変数を隠すことができる理由でもあります。


@jecxjoの答えが部分的に間違っています。上書きY(または)割り当てを防ぐことは、そのエントリが使用されますが割り当てられていないことBUILDです。つまり、最初のコードは正確に望むものではなく、次のものを使用します。:===:=

X = release
debug: X = debug
debug: all

# Note the '=' assignment instead of the ':='
Y = $(X)
BUILD = $(Y)

all:
    @echo $(BUILD)

これは実際に書き換えの対象ではなく、問題を解決する彼の答えの変更です。ただし、これらの割り当ては編集できない他のファイルに含まれていると述べたため、これは解決策ではありません。

関連情報