# make(1) ## Anatomy of `make` rules ```make 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: ```make %.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. ```make # file: Makefile all: foobar blabla foo% bla%: aaa bbb bbb @echo "@ = $@" @echo "< = $<" @echo "^ = $^" @echo "+ = $+" @echo "* = $*" @echo "----" aaa: bbb: ``` Running above `Makefile` gives: ```text @ = 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 ```make define my_var @echo foo @echo bar endef all: $(my_var) ``` Running above `Makefile` gives: ```text foo bar ``` ## Arguments Arguments specified on the command line *override* ordinary variable assignments in the makefile ([overriding variables][make-var-override]). ```make VAR = abc all: @echo VAR=$(VAR) ``` ```text # make VAR=abc # make VAR=123 VAR=123 ``` ## Useful functions ### Substitution references Substitute strings matching pattern in a list. ```make in := a.o l.a c.o out := $(in:.o=.c) # => out = a.c l.a c.c ``` ### `patsubst` ([ref][make-patsubst]) ```make 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. ```make 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. ```make 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). ```make $(abspath fname1 fname2 ..) ``` ### `realpath` Resolve each file name as canonical path. ```make $(realpath fname1 fname2 ..) ``` ### `call` ([ref][make-call]) Invoke parametrized function, which is an expression saved in a variable. ```make swap = $(2) $(1) all: @echo "call swap first second -> $(call swap,first,second)" ``` Outputs: ```text call swap first second -> second first ``` ### `eval` ([ref][make-eval]) Allows to define new makefile constructs by evaluating the result of a variable or function. ```make define new_rule $(1): @echo "$(1) -> $(2)" endef default: rule1 rule2 $(eval $(call new_rule,rule1,foo)) $(eval $(call new_rule,rule2,bar)) ``` Outputs: ```text rule1 -> foo rule2 -> bar ``` ### foreach ([ref][make-foreach]) Repeat a piece of text for a list of values, given the syntax `$(foreach var,list,text)`. ```make myfn = x$(1)x default: @echo $(foreach V,foo bar baz,$(call myfn,$(V))) ``` Outputs: ```text xfoox xbarx xbazx ``` ## Examples ### Config based settings ```make 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. ```sh $ 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 ```make 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: ```text rule1 -> foo rule2 -> bar ``` > Use `make -R -p` to print the make database including the rules. [make-var-override]: https://www.gnu.org/software/make/manual/html_node/Overriding.html [make-patsubst]: https://www.gnu.org/software/make/manual/html_node/Text-Functions.html#index-patsubst-1 [make-call]: https://www.gnu.org/software/make/manual/html_node/Call-Function.html [make-eval]: https://www.gnu.org/software/make/manual/html_node/Eval-Function.html [make-foreach]: https://www.gnu.org/software/make/manual/html_node/Foreach-Function.html