make(1)

Anatomy of make rules

target .. : prerequisite ..
	recipe
	..
  • target: an output generated by the rule
  • prerequisite: an input that is used to generate the target
  • recipe: list of actions to generate the output from the input

Use make -p to print all rules and variables (implicitly + explicitly defined).

Pattern rules & variables

Pattern rules

A pattern rule contains the % char (exactly one of them) and look like this example:

%.o : %.c
	$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

The target matches files of the pattern %.o, where % matches any none-empty substring and other character match just them self.

The substring matched by % is called the stem.

% in the prerequisite stands for the matched stem in the target.

Automatic variables

As targets and prerequisites in pattern rules can't be spelled explicitly in the recipe, make provides a set of automatic variables to work with:

  • $@: Name of the target that triggered the rule.
  • $<: Name of the first prerequisite.
  • $^: Names of all prerequisites (without duplicates).
  • $+: Names of all prerequisites (with duplicates).
  • $*: Stem of the pattern rule.
# file: Makefile

all: foobar blabla

foo% bla%: aaa bbb bbb
	@echo "@ = $@"
	@echo "< = $<"
	@echo "^ = $^"
	@echo "+ = $+"
	@echo "* = $*"
	@echo "----"

aaa:
bbb:

Running above Makefile gives:

@ = foobar
< = aaa
^ = aaa bbb
+ = aaa bbb bbb
* = bar
----
@ = blabla
< = aaa
^ = aaa bbb
+ = aaa bbb bbb
* = bla
----

Variables related to filesystem paths:

  • $(CURDIR): Path of current working dir after using make -C path

Multi-line variables

define my_var
@echo foo
@echo bar
endef

all:
	$(my_var)

Running above Makefile gives:

foo
bar

Arguments

Arguments specified on the command line override ordinary variable assignments in the makefile (overriding variables).

VAR = abc
all:
	@echo VAR=$(VAR)
# make
VAR=abc

# make VAR=123
VAR=123

Useful functions

Substitution references

Substitute strings matching pattern in a list.

in  := a.o l.a c.o
out := $(in:.o=.c)
# => out = a.c l.a c.c

patsubst (ref)

in  := a.c b.c
out := $(patsubst %.c, build/%.o, $(in))
# => out = build/a.o build/b.o

# This is actually equivalent to $(in:%.c=build/%.o)

filter

Keep strings matching a pattern in a list.

in  := a.a b.b c.c d.d
out := $(filter %.b %.c, $(in))
# => out = b.b c.c

filter-out

Remove strings matching a pattern from a list.

in  := a.a b.b c.c d.d
out := $(filter-out %.b %.c, $(in))
# => out = a.a d.d

abspath

Resolve each file name as absolute path (don't resolve symlinks).

$(abspath fname1 fname2 ..)

realpath

Resolve each file name as canonical path.

$(realpath fname1 fname2 ..)

call (ref)

Invoke parametrized function, which is an expression saved in a variable.

swap = $(2) $(1)

all:
	@echo "call swap first second -> $(call swap,first,second)"

Outputs:

call swap first second -> second first

eval (ref)

Allows to define new makefile constructs by evaluating the result of a variable or function.

define new_rule
$(1):
	@echo "$(1) -> $(2)"
endef

default: rule1 rule2

$(eval $(call new_rule,rule1,foo))
$(eval $(call new_rule,rule2,bar))

Outputs:

rule1 -> foo
rule2 -> bar

foreach (ref)

Repeat a piece of text for a list of values, given the syntax $(foreach var,list,text).

myfn = x$(1)x

default:
	@echo $(foreach V,foo bar baz,$(call myfn,$(V)))

Outputs:

xfoox xbarx xbazx

Examples

Config based settings

conf-y      := default
conf-$(FOO) := $(conf-y) foo
conf-$(BAR) := $(conf-y) bar

libs-y      := libdef
libs-$(FOO) += libfoo
libs-$(BAR) += libbar

all:
	@echo "conf-y: $(conf-y)"
	@echo "libs-y: $(libs-y)"

Yields the following results.

$ make
conf-y: default
libs-y: libdef

$ make FOO=y
conf-y: default foo
libs-y: libdef libfoo

$ make BAR=y
conf-y: default bar
libs-y: libdef libbar

$ make FOO=y BAR=y
conf-y: default foo bar
libs-y: libdef libfoo libbar

Using foreach / eval / call to generate new rules

define new_rule
$(1):
	@echo "$(1) -> $(2)"
endef

arg-rule1 = foo
arg-rule2 = bar

RULES = rule1 rule2

all: $(RULES)

$(foreach R,$(RULES),$(eval $(call new_rule,$(R),$(arg-$(R)))))

# equivalent to
#   $(eval $(call new_rule,rule1,foo))
#   $(eval $(call new_rule,rule2,bar))

Outputs:

rule1 -> foo
rule2 -> bar

Use make -R -p to print the make database including the rules.