web-dev-qa-db-ja.com

GNU Makefile変数割り当て=、?=、:=、および+ =?の違いは何ですか?

どのようにして変数代入がMakefileで実際に機能するのかについて、誰でも明確な説明を与えることができます。

違いは何ですか :

 VARIABLE = value
 VARIABLE ?= value
 VARIABLE := value
 VARIABLE += value

GNU Makeのマニュアルの セクション を読みましたが、それでも私には意味がありません。

700
mmoris

遅延セット

VARIABLE = value

変数の通常の設定 - その中の値は宣言された時ではなく、使われた時に再帰的に展開されます

即時セット

VARIABLE := value

内部の値を単純に展開した変数の設定 - その中の値は宣言時に展開されます。

存在しない場合に設定

VARIABLE ?= value

値を持たない場合にのみ変数を設定する

追加

VARIABLE += value

指定された値を既存の値に追加します(または変数が存在しない場合はその値に設定します)。

940
Alnitak

=を使用すると、変数に値が割り当てられます。変数にすでに値がある場合は、それが置き換えられます。この値は使用時に拡張されます。例えば:

HELLO = world
HELLO_WORLD = $(HELLO) world!

# This echoes "world world!"
echo $(HELLO_WORLD)

HELLO = hello

# This echoes "hello world!"
echo $(HELLO_WORLD)

:=の使用は、=の使用と似ています。ただし、値が使用時に拡張されるのではなく、代入中に拡張されます。例えば:

HELLO = world
HELLO_WORLD := $(HELLO) world!

# This echoes "world world!"
echo $(HELLO_WORLD)

HELLO = hello

# Still echoes "world world!"
echo $(HELLO_WORLD)

HELLO_WORLD := $(HELLO) world!

# This echoes "hello world!"
echo $(HELLO_WORLD)

?=を使用すると、変数に値 iff が割り当てられていません。変数に以前空の値(VAR=)が割り当てられていた場合、それはまだ設定されていると見なされますと思います。それ以外の場合、=とまったく同じように機能します。

+=を使用するのは=を使用するのと似ていますが、値を置き換えるのではなく、値が現在の値に追加され、その間にスペースが入ります。変数が以前に:=で設定されていた場合、それは展開されますと思います。結果の値は使用時に展開されますと思います。例えば:

HELLO_WORLD = hello
HELLO_WORLD += world!

# This echoes "hello world!"
echo $(HELLO_WORLD)

HELLO_WORLD = $(HELLO_WORLD) world!のようなものが使われた場合、再帰が起こり、それがあなたのMakefileの実行を終わらせるでしょう。 A := $(A) $(B)が使用された場合、B+=で拡張されるのに対して:=Bが拡張されないため、結果は+=を使用する場合とまったく同じにはなりません。

241
strager

私はあなたが "make"を使っていくつかの実験をすることを勧めます。これは=:=の違いを示す簡単なデモです。

/* Filename: Makefile*/
x := foo
y := $(x) bar
x := later

a = foo
b = $(a) bar
a = later

test:
    @echo x - $(x)
    @echo y - $(y)
    @echo a - $(a)
    @echo b - $(b)

make testが出力します。

x - later
y - foo bar
a - later
b - later bar

より詳しい説明をここでチェックしてください

53
nickand

VARIABLE = valueを使用するとき、valueが実際に別の変数への参照である場合、その値はVARIABLEが使用されているときにのみ決定されます。これは例で最もよく説明されています。

VAL = foo
VARIABLE = $(VAL)
VAL = bar

# VARIABLE and VAL will both evaluate to "bar"

VARIABLE := valueを使用すると、value の値が になります。例えば:

VAL = foo
VARIABLE := $(VAL)
VAL = bar

# VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"

VARIABLE ?= valを使用するということは、VARIABLE の値のみを設定することを意味します VARIABLEがまだ設定されていない場合。まだ設定されていない場合、値の設定はVARIABLEが使用されるまで延期されます(例1のように)。

VARIABLE += valuevalueVARIABLEに追加するだけです。 valueの実際の値は、=または:=を使用して、最初に設定されたときの値として決定されます。

31
mipadi

上記の答えでは、「値は宣言時または使用時に拡張される」という意味を理解することが重要です*.cのような値を与えても、何も展開されません。この文字列がコマンドによって使用される場合にのみ、それが何らかのグロビングを引き起こす可能性があります。同様に、$(wildcard *.c)$(Shell ls *.c)のような値は展開を必要とせず、変数の定義で:=を使用していても定義時に完全に評価されます。

いくつかのCファイルがあるディレクトリで次のMakefileを試してください。

VAR1 = *.c
VAR2 := *.c
VAR3 = $(wildcard *.c)
VAR4 := $(wildcard *.c)
VAR5 = $(Shell ls *.c)
VAR6 := $(Shell ls *.c)

all :
    touch foo.c
    @echo "now VAR1 = \"$(VAR1)\"" ; ls $(VAR1)
    @echo "now VAR2 = \"$(VAR2)\"" ; ls $(VAR2)
    @echo "now VAR3 = \"$(VAR3)\"" ; ls $(VAR3)
    @echo "now VAR4 = \"$(VAR4)\"" ; ls $(VAR4)
    @echo "now VAR5 = \"$(VAR5)\"" ; ls $(VAR5)
    @echo "now VAR6 = \"$(VAR6)\"" ; ls $(VAR6)
    rm -v foo.c

makeを実行すると、foo.cという名前の余分な(空の)Cファイルを作成するルールがトリガーされますが、6つの変数のどれにもその値にfoo.cがありません。

6
phs