Make Built-in Functions Reference

Learn essential Make functions: wildcard, patsubst, filter, foreach, call, shell, and text manipulation functions with practical build system examples.

Reference

Detailed Explanation

Essential Make Functions

Make provides built-in functions for string manipulation, file operations, and flow control. These functions are invoked with $(function arguments) syntax.

File Functions

# Find all .c files recursively
SRCS := $(shell find src -name '*.c')

# Find .c files in one directory (no shell)
SRCS := $(wildcard src/*.c)

# Convert .c files to .o files
OBJS := $(patsubst src/%.c,build/%.o,$(SRCS))

# Alternative substitution syntax
OBJS := $(SRCS:.c=.o)

wildcard expands glob patterns. patsubst performs pattern substitution with % as the wildcard. The :.c=.o shorthand is equivalent to patsubst %.c,%.o.

String Functions

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

# Filter: keep only matching words
TEST_SRCS = $(filter test_%,$(SRCS))
# Result: test_main.c test_utils.c

# Filter-out: remove matching words
PROD_SRCS = $(filter-out test_%,$(SRCS))
# Result: main.c utils.c

# Sort and deduplicate
UNIQUE = $(sort z a m a z)
# Result: a m z

# Word functions
FIRST = $(firstword $(SRCS))
# Result: main.c
COUNT = $(words $(SRCS))
# Result: 4

Foreach and Call

DIRS = src lib tests

# Create all directories
$(foreach d,$(DIRS),$(shell mkdir -p $(d)))

# Generate rules with define/call
define COMPILE_RULE
$(2)/%.o: $(1)/%.c
	@mkdir -p $$(@D)
	$$(CC) $$(CFLAGS) -c -o $$@ $$<
endef

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

Conditional Functions

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

# $(or ...) — first non-empty value
PYTHON := $(or $(shell which python3),$(shell which python),python)

# $(and ...) — empty if any arg is empty
HAS_TOOLS := $(and $(shell which gcc),$(shell which make))

The shell Function

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

$(shell ...) executes a command and captures its stdout. Use := (immediate assignment) to run the command once at parse time, not on every reference.

Key Tips

  • Use $(wildcard) instead of $(shell find ...) when possible — it is faster
  • $(sort) both sorts and removes duplicates
  • $(strip) removes leading/trailing whitespace — useful after variable expansion
  • Always use := with $(shell) to avoid re-executing commands

Use Case

Writing advanced Makefile rules that need to manipulate file lists, filter sources, generate targets dynamically, and use conditional logic based on available system tools.

Try It — Makefile Generator

Open full tool