Make組み込み関数リファレンス

必須のMake関数を学びます:wildcard、patsubst、filter、foreach、call、shell、およびテキスト操作関数を実用的なビルドシステムの例とともに。

Reference

詳細な説明

必須のMake関数

Makeは文字列操作、ファイル操作、フロー制御のための組み込み関数を提供します。これらの関数は$(function arguments)構文で呼び出されます。

ファイル関数

# 再帰的にすべての.cファイルを検索
SRCS := $(shell find src -name '*.c')

# 1つのディレクトリの.cファイルを検索(shellなし)
SRCS := $(wildcard src/*.c)

# .cファイルを.oファイルに変換
OBJS := $(patsubst src/%.c,build/%.o,$(SRCS))

# 代替置換構文
OBJS := $(SRCS:.c=.o)

wildcardはglobパターンを展開します。patsubst%をワイルドカードとしてパターン置換を行います。:.c=.o省略形はpatsubst %.c,%.oと同等です。

文字列関数

SRCS = main.c utils.c test_main.c test_utils.c

# filter:マッチする単語のみを保持
TEST_SRCS = $(filter test_%,$(SRCS))
# 結果: test_main.c test_utils.c

# filter-out:マッチする単語を削除
PROD_SRCS = $(filter-out test_%,$(SRCS))
# 結果: main.c utils.c

# ソートと重複除去
UNIQUE = $(sort z a m a z)
# 結果: a m z

# 単語関数
FIRST = $(firstword $(SRCS))
# 結果: main.c
COUNT = $(words $(SRCS))
# 結果: 4

foreachとcall

DIRS = src lib tests

# すべてのディレクトリを作成
$(foreach d,$(DIRS),$(shell mkdir -p $(d)))

# define/callでルールを生成
define COMPILE_RULE
$(2)/%.o: $(1)/%.c
	@mkdir -p $$(@D)
	$$(CC) $$(CFLAGS) -c -o $$@ $$<
endef

$(eval $(call COMPILE_RULE,src,build))

条件関数

# $(if condition,then,else)
CC := $(if $(shell which clang 2>/dev/null),clang,gcc)

# $(or ...) — 最初の空でない値
PYTHON := $(or $(shell which python3),$(shell which python),python)

# $(and ...) — いずれかの引数が空の場合は空
HAS_TOOLS := $(and $(shell which gcc),$(shell which make))

shell関数

GIT_HASH := $(shell git rev-parse --short HEAD)
NUM_CPUS := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu)

$(shell ...)はコマンドを実行してその標準出力をキャプチャします。:=(即時代入)を使用して、参照のたびにではなくパース時に一度だけコマンドを実行します。

主要なヒント

  • 可能な場合は$(shell find ...)の代わりに$(wildcard)を使用する — より高速
  • $(sort)はソートと重複除去の両方を行う
  • $(strip)は先頭/末尾の空白を削除する — 変数展開後に便利
  • $(shell)には常に:=を使用して、コマンドの再実行を避ける

ユースケース

ファイルリストの操作、ソースのフィルタリング、動的なターゲット生成、利用可能なシステムツールに基づく条件分岐ロジックが必要な高度なMakefileルールを書く場合に使用します。

試してみる — Makefile Generator

フルツールを開く