# 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 & Automatic 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` ## 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 ..) ``` ## 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 ``` [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