複数実行ファイルのマルチバイナリMakefile
foreachとcall関数を使用してDRYなターゲット生成で、別々のソースディレクトリから複数の実行ファイルをビルドするMakefileを作成します。
Build Patterns
詳細な説明
複数バイナリのビルド
複数の実行ファイルを生成するプロジェクト(例:サーバーとCLIクライアント)は、各バイナリのビルドルールを重複させないMakefileが必要です。
foreachの使用
BINARIES = server client worker
BIN_DIR = bin
all: $(addprefix $(BIN_DIR)/,$(BINARIES))
$(BIN_DIR)/%: cmd/%/main.go
@mkdir -p $(BIN_DIR)
go build -o $@ ./cmd/$*/...
addprefix関数は各バイナリ名にbin/を付加します。%パターンは任意のバイナリ名にマッチし、$*はマッチしたステムを返します。この単一のルールが、それぞれのcmd/ディレクトリから3つすべてのバイナリをビルドします。
defineとcallの使用(上級)
define BUILD_BINARY
$(BIN_DIR)/$(1): $$(wildcard cmd/$(1)/*.go)
@mkdir -p $(BIN_DIR)
go build -o $$@ ./cmd/$(1)/...
endef
$(foreach bin,$(BINARIES),$(eval $(call BUILD_BINARY,$(bin))))
defineブロックはテンプレートを作成します。call関数は$(1)を各バイナリ名で置換します。eval関数は結果をMakefile構文として扱います。$$エスケープに注意してください。define内でルール実行時(eval時ではなく)に展開されるべき変数にはダブルドルエスケープが必要です。
個別のビルド設定
server: CFLAGS += -DSERVER_MODE
client: CFLAGS += -DCLIENT_MODE
server client: %: src/%.c src/common.c
$(CC) $(CFLAGS) -o $(BIN_DIR)/$@ $^
ターゲット固有の変数代入により、他に影響を与えずに個々のバイナリにフラグを追加できます。静的パターンルール%: src/%.cはリストされたターゲットにのみ適用されます。
主要なテクニック
addprefixとaddsuffixはファイル名のリストを操作する- 静的パターンルール(
targets: pattern: prereqs)はパターンマッチングを制限する - ターゲット固有の変数はターゲットごとの設定を提供する
foreach/eval/callパターンはルールを動的に生成する
ユースケース
共通のソースコードを共有しながら、異なるビルド設定で別々の実行ファイルが必要なマイクロサービスモノレポをビルドする場合に使用します。