変数の基本概念
Makefileにおける変数は、テキスト文字列を保持する識別子であり、ルールのターゲット・依存関係・コマンドなどに展開して利用できる。変数名には:、#、=、空白を含めることはできない。慣例として大文字が使われることが多いが、内部用途には小文字を使うことを推奨する。
変数参照は$(VAR)または${VAR}で行う。$$はリテラルのドル記号を表す。以下は典型的な使用例:
OBJS = main.o utils.o parser.o
app: $(OBJS)
gcc -o app $(OBJS)
$(OBJS): config.h
変数の種類と代入方法
再帰的展開(=)
値は参照時に展開される。他の変数や関数への参照が含まれる場合、その都度評価される。
CC = gcc
CFLAGS = $(WARNINGS) -O2
WARNINGS = -Wall
build:
@echo $(CFLAGS) # 出力: -Wall -O2
ただし、CFLAGS = $(CFLAGS) -gのような自己参照は無限ループを引き起こすため注意が必要。
単純展開(:= または ::=)
定義時点で値を一度だけ展開し、その後はリテラルとして扱われる。
X := alpha
Y := $(X) beta
X := gamma
# Y の値は "alpha beta"(X の再定義後も変化しない)
先頭スペースを保持したい場合は次のようにする:
empty :=
space := $(empty) #
即時展開(:::=)
定義時に一度展開され、結果がエスケープされて保存される。使用時には再度展開されるが、変数や関数は評価されない。
val = one$$two
VAR :::= $(val)
val = three$$four
# VAR の値は "one$$two"
# 使用時: $(VAR) → "one$two"
条件付き代入(?=)
変数が未定義の場合のみ代入する。
INSTALL_DIR ?= /usr/local/bin
高度な変数操作
置換参照
$(VAR:a=b)形式で末尾一致置換が可能。ワイルドカードを使用したパターン置換もサポート。
SOURCES = foo.c bar.c baz.S
OBJECTS = $(SOURCES:.c=.o) # foo.o bar.o baz.S
OBJS = $(SOURCES:%.c=%.o) # 同上(パターン指定)
計算された変数名
変数名自体を動的に構築できる。
arch = x86
x86_flags = -m32
flags = $($(arch)_flags) # flags = "-m32"
複雑なケースでは複数レベルのネストも可能だが、可読性に注意が必要。
変数の管理と特殊機能
変数への追加(+=)
既存の値にテキストを追加。変数の種類に応じて動作が異なる:
- 再帰的変数:未展開のまま追加
- 単純展開変数:新値を展開して追加
CFLAGS = -O2
CFLAGS += -g # 再帰的 → "-O2 -g"(-O2内の変数参照は維持)
overrideディレクティブ
コマンドラインで指定された変数を上書き可能にする。
override CFLAGS += -DDEBUG
複数行変数(define)
改行を含む値を定義できる。
define HEADER
#ifndef CONFIG_H
#define CONFIG_H
#endif
endef
変数の未定義化(undefine)
変数を完全に削除(空文字とは異なる)。
undefine TEMP_VAR
override undefine USER_CFLAGS # コマンドライン変数も対象
特殊な変数スコープ
ターゲット固有変数
特定のターゲットでのみ有効な変数値を設定。
debug: CFLAGS = -g -O0
debug: app
release: CFLAGS = -O3
release: app
依存ファイルにも継承されるが、private修飾子で抑制可能:
main: private LDFLAGS = -static
main: main.o
パターン固有変数
ファイルパターンにマッチするターゲットに適用。
%.o: CFLAGS = -fPIC
lib/%.o: CFLAGS = -fPIC -g # より具体的なパターンが優先
組み込み特殊変数
- MAKEFILE_LIST: 解析中のMakefileパスのリスト
- .DEFAULT_GOAL: デフォルトターゲットの設定/取得
- .VARIABLES: 定義済み全変数名のリスト
- .FEATURES: サポート機能の一覧(jobserver, guile等)
- .EXTRA_PREREQS: 自動変数に含まれない依存関係の追加
# .EXTRA_PREREQSの使用例
myapp: myapp.o
myapp: .EXTRA_PREREQS = $(CC)