makefile でよく使う “=” と “:=” は、変数の値をいつ確定させるかが違います。あわせて、追記に使う “+=” の挙動も押さえておくと安全です。
B := one
A = $(B) # 遅延展開 (=)。参照時に $(B) を評価する
C := $(B) # 即時展開 (:=)。この時点の $(B)="one" を保存する
B := two
all:
@echo A=$(A) # two (実行時点で B=two を見る)
@echo C=$(C) # one (定義時点の値を保持)この例では、A は実行時点の B を見るので two、C は定義時点の B を固定したので one になります。
“+=” は、変数に文字列を追加します。すでに値がある場合は、先頭に 1 つの空白をはさんでから追加します。未定義の変数に対して最初に使った場合は、“=” と同じく遅延展開の変数として定義します。
ただし、すでに変数が定義されている場合は、もとの変数の種類によって挙動が変わります。
X := value
X += more
X := $(X) moreX = value
X += moreこの違いは、右辺に他の変数参照が含まれるときに重要です。次の例では、includes の定義が後から来ても保持したいので、CFLAGS は遅延展開(“=”)のままにし、追記には “+=” を使います。
CFLAGS = $(includes) -O
CFLAGS += -pg # プロファイリングを有効化もしここで
CFLAGS := $(CFLAGS) -pgとしてしまうと、この時点で $(CFLAGS) が展開され、includes が未定義ならその参照が消えてしまいます。結果として、後から includes を定義しても反映されません。
まだ一度も設定されていない変数にだけ値を入れる方法です。条件付き代入(conditional assignment)では、“?=” を使います。環境変数やコマンドラインで設定済みのときも「設定済み」と見なして何もしません。新しく定義される場合の種類は遅延展開です。
FOO ?= default等価表現は次の通りです。
ifeq ($(origin FOO), undefined)
FOO = default
endif即時展開のデフォルトが欲しいときは、上の等価表現で “:=” を使います。
例として、日時などを 1 度だけ決めたい場合は “:=” が向きます。
BUILD_TIME := $(shell date +%Y%m%d-%H%M%S)