Functions let a Makefile discover files and transform names instead of hard-coding every path.
Function calls look like $(name arg1,arg2). Note there is no space after commas unless you want it in the value. The most useful:
$(wildcard src/*.c)the files matching a glob (only ones that exist now).$(patsubst %.c,%.o,$(SRC))replaces by pattern; the shorthand$(SRC:.c=.o)does the same for suffixes.$(subst from,to,text)plain substring replacement.$(filter %.c,$(FILES))keeps matching words;filter-outdrops them.$(addprefix build/,$(OBJ)),$(addsuffix ...),$(notdir ...),$(dir ...),$(basename ...).$(sort list)sorts and removes duplicates;$(words ...),$(word n,...),$(firstword ...).$(foreach v,list,text)repeats text for each word.$(shell cmd)runs a shell command and inserts its output (newlines become spaces).$(if cond,then,else),$(error msg),$(warning msg),$(info msg)for checks and debugging.
make thinks in space-separated words, so file names containing spaces are effectively unsupported. Keep build paths free of spaces.
Assign function results with := so they're evaluated once. With =, a $(shell ...) call would run again every time the variable is used.
Example
SRC := $(wildcard src/*.c)
OBJ := $(patsubst src/%.c,build/%.o,$(SRC))
NAMES := $(notdir $(basename $(SRC)))
TESTS := $(filter test_%,$(NAMES))
DIRS := $(sort $(dir $(OBJ)) build/ build/)
GIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo none)
ifeq ($(SRC),)
$(error no sources found in src/)
endif
show:
@echo SRC=$(SRC)
@echo OBJ=$(OBJ)
@echo NAMES=$(NAMES) TESTS=$(TESTS)
@echo DIRS=$(DIRS) GIT=$(GIT)
@echo $(foreach n,$(NAMES),bin/$(n))
# with src/main.c, src/util.c, src/test_util.c:
# SRC=src/main.c src/test_util.c src/util.c
# OBJ=build/main.o build/test_util.o build/util.o
# NAMES=main test_util util TESTS=test_util
# DIRS=build/ GIT=none
# bin/main bin/test_util bin/utilRemember
- $(wildcard), $(patsubst) and $(SRC:.c=.o) build file lists
- filter, addprefix, notdir, sort and foreach transform word lists
- Assign $(shell ...) with := so it runs once
Watch out for
- Adding a space after a comma, as in $(subst a, b,x), which puts the space into the result.