
ターゲット固有の変数を強制的にすぐに設定する方法(ライン2)?私が望む結果はmake
torelease
とmake debug
to 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
範囲内のグローバル変数が非表示になるために機能します。BUILD
debug:
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)
これは実際に書き換えの対象ではなく、問題を解決する彼の答えの変更です。ただし、これらの割り当ては編集できない他のファイルに含まれていると述べたため、これは解決策ではありません。