GNU Make


Basics

Force rebuild:

Run recipe in parallel:

Touch all prerequisites of a target:

Automatic variables:

Variables:


Advanced

Make dependency only if file doesn’t exist (i.e. ignore time-stamps):

See https://stackoverflow.com/a/21754930/3362993

# 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:

See http://stackoverflow.com/a/7081747/897303

.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


References

https://swcarpentry.github.io/make-novice/