GNU Make
Basics
$ make foo
Force rebuild:
$make -B foo
Run recipe in parallel:
$make -j foo
Touch all prerequisites of a target:
make foo.pdf --touch
$@
- the target$<
- first prerequisite$^
- all prerequisites$(<F)
- file part of first prerequisite$(<D)
- directory part of first prerequisite$(@D)
- directory part of target$(@F)
- file-within-directory part of target$*
- the “stem” of a pattern rule%
- wildcard
make foo=bar
- pass a variable from the command line?=
- set a default value if not passed above:=
- assign the output of a function
Advanced
Make dependency only if file doesn’t exist (i.e. ignore time-stamps):
# examples/foo.h will only be built if it doesn't exist
# the time-stamps of items to the right of | are ignored
examples/foo.h : | foo.h
cp $| $@
Multiple targets:
See https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html
## independent
bigoutput littleoutput : text.g
generate text.g -$(subst output,,$@) > $@
# is equivalent to
bigoutput : text.g
generate text.g -big > bigoutput
littleoutput : text.g
generate text.g -little > littleoutput
## grouped, all targets are updated from recipe iteration
foo bar biz &: baz boz
echo $^ > foo
echo $^ > bar
echo $^ > biz
Misc
.PHONY
for indicating not-real targets:
.PHONY: all doc clean
Self-documenting Makefiles:
See https://swcarpentry.github.io/make-novice/08-self-doc/index.html
.PHONY : help all
help : Makefile
@sed -n 's/^##//p' $<
## all: Make everything.
all:
@echo "Hello World"
See https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'^S
all: ## Make everything.
@echo "Hello World"
Examples
https://github.com/jsta/makefile-recipes