Makefileのincludeとモジュラー構造
includeディレクティブを使用して大規模なMakefileを変数、ルール、環境固有の設定用の再利用可能なモジュールに分割して整理します。
Advanced Patterns
詳細な説明
includeによるモジュラーMakefile
大規模プロジェクトはMakefileを複数のファイルに分割することで恩恵を受けます。includeディレクティブは他のMakefileの内容を読み込んで挿入します。
基本的なinclude
# Makefile
include config.mk
include rules.mk
all: $(TARGET)
# config.mk
CC ?= gcc
CFLAGS ?= -Wall -O2
TARGET = myapp
SRCS = $(wildcard src/*.c)
OBJS = $(SRCS:.c=.o)
# rules.mk
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-includeによるサイレントインクルード
-include local.mk
-include $(DEPS)
-include(またはsinclude)バリアントはファイルが存在しなくてもエラーになりません。以下に不可欠です:
- 最初のビルド時に存在しない依存関係ファイル(
.d) - 開発者がオプションで作成するローカルオーバーライド(
local.mk)
環境固有のオーバーライド
ENV ?= development
include config/$(ENV).mk
# config/development.mk
CFLAGS += -g -O0 -DDEBUG
LDFLAGS += -fsanitize=address
# config/production.mk
CFLAGS += -O3 -DNDEBUG -flto
LDFLAGS += -flto -s
環境の切り替え:make ENV=production。
モノレポパターン
SERVICES = auth api gateway worker
define SERVICE_RULES
.PHONY: build-$(1) test-$(1)
build-$(1):
$(MAKE) -C services/$(1) build
test-$(1):
$(MAKE) -C services/$(1) test
endef
$(foreach svc,$(SERVICES),$(eval $(call SERVICE_RULES,$(svc))))
build-all: $(addprefix build-,$(SERVICES))
test-all: $(addprefix test-,$(SERVICES))
$(MAKE) -Cパターンは各サービスディレクトリのサブMakefileに委譲し、foreach/eval/callパターンは各サービスのビルドとテストターゲットを生成します。
重要なポイント
includeパスはMakefileの場所ではなく、作業ディレクトリに対して相対的includeの前に定義された変数はインクルードされたファイルで利用可能- 循環インクルードは検出されず、無限ループを引き起こす
- 現在のMakefileのパスを取得するには
MAKEFILE_LISTを使用する
ユースケース
Makefileを環境設定、共有ルール、サービス固有のターゲットに分割して保守性を向上させる大規模プロジェクトやモノレポのビルドシステムを整理する場合に使用します。