
wiki | english wikibooks |
gnu | home docs |
bsd | man |
posix | home |
fork | https://justine.lol/make/ |
alternatives | just Task Snakemake |
- 1976, at Bell Labs
- by Stuart Feldman
cli
make [-f Makefile] [VAR="foo"] [OPTIONS] [TARGETS]
- bare run of "make", defaults to running the first target found
- you can give more than 1 target
-f | –(make)file | file | |
-o | –old-file | target | never remake TARGET |
-k | –keep-going | keep on errors | |
-s | –silent | silent command print | |
-i | –ignore-errors | ||
-e | –environment-overrides | env>make vars | |
-B | –always-make | make ALL targets | |
-j | –jobs | n_jobs | parallel jobs |
-n | –dry-run | ||
-t | –touch | touch targets, without running | |
-d | –debug | [abvijmn] | print debug |
–warn-undefined-variables | when referenced | ||
-r | –no-builtin-rules | ||
-R | –no-builtin-variables |
language

- defines a dependency tree (DAG) of
rules
(aka recipe)- between his structure and dependencies
- made of
targets
(the vertices) - final exe is the root vertex
- use
include MAKEFILE
to include another Makefile
target / output
- targets without deps are human made ones
- order does not matter
- but if multiple % patterns match, will use the last one matched (deps stills stacked?)
- multiple targets: for same dependencies
- recommended phony ones: https://www.gnu.org/software/make/manual/html_node/Standard-Targets.html
- all, help, clean, check, dist, run, deps, serve, deploy
- test: make it depend of the final binary
- (un)install: use PREFIX=/usr/local and DESTDIR
special targets
.ONESHELL: | runs all commands the same shell |
.POSIX: | should be the first line |
.SUFFIXES: | disable all default inference rules |
.DELETE_ON_ERROR: | will delete the target if a command fails (NO BY DEFAULT) |
.PHONY: | make target not a regular target file |
default targets
- https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html
- https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html
%: ; $(CC) $*.o -o $* %.c: ; $(CC) -c $(CPPFLAGS) $(CFLAGS) %.cpp: ; $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) %.o: ; $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(DLIBS)
prerequisites / dependency
can be split into different targets with the same name (?
* | wildcard, filesystem matches, use it with $(wildcard) |
% | wildcard |
commands / actions
- uses /bin/sh by default
- TAB indented
- use (\) for long ones
- use (;) to make one command of many
- each one runs on his own shell
- whole makefile fails if a command returns 1
prefixes
- ignore errors @ not print the command, use it to add indent comments + run even on no-exec mode
variables / macros
- are ALWAYS strings
- undefined variables are treated as empty strings (see –warn-undefined-variables)
- order of precedence (see override)
- cli
- makefile
- environment
- predefined
referencing
$a # for length=1 vars $(ab) # for length>1 vars ${ab} # " $(ab:.cpp=.o) # string replace
assignments
- ONLY evaluated when they are used
= | dynamic/macro, evaluated each time is used |
:= | one time, evaluated procedurally |
::= | " |
?= | safe, only if undefined |
+= | appends with a space |
!= | exec shell command and assign it |
implicit / predefined / default
https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
CC | For compiler and compiler flags |
CXX | " |
CFLAGS | " |
CPPFLAGS | |
CXXFLAGS | |
LDFLAGS | for flags passed to compiler when linking |
LDLIBS | For flags about libraries when linking |
SHELL | eg: "bash" |
MAKE_FLAGS | |
MAKEFILE_LIST | |
.SHELLFLAGS | eg: "-eu -o pipefail -c" |
.RECIPEPREFIX | use instead of tabs |
.DEFAULT_GOAL | default target |
magic / automatic variables
https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html
$@ | target's name (always one) |
$(@D) | target's dir(name) |
$(@F) | target's base(name) |
$< | 1st prerequisite |
$(<D) | 1st prerequisite's dir(name) |
$(<F) | 1st prerequisite's base(name) |
$^ | all prerequisites |
$+ | all prerequisites, with dups |
$? | new prerequisites (than the target) |
$* | what "%" wildcard matched |
$$ | literal "$" |
$% | target's name, WHEN (ar)chive member ? |
$¦ | ? order-only prerequisites ? |
functions
- https://www.gnu.org/software/make/manual/html_node/Functions.html
- do NOT add spaces between arguments, functions will see it
shell | cmd | exec and replaces \n with space |
strings
https://www.gnu.org/software/make/manual/html_node/Text-Functions.html
word | n,text | "n"th word in in text |
wordlist | n,m,text | text word-slicing from "n" to "m" |
words | text | number of words |
firstword | text | |
lastword | text | |
findstring | needle,text | returns "needle" or "" if not in text |
filter | pat%..,text | remove words that match "pat%" |
filter-out | pat%..,text | remove words that do NOT match "pat%" |
sort | text | sort words, remove dups |
strip | text | trim and squash whitespaces |
subst | from,to,text | substitute literal words |
patsubst | pat,repl,text | substitute pattern% words, text can use * |
filenames
https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html
join | list,list | zipWith (<>) |
wildcard | glob*Path | filesystem match, space separated if many |
(not)dir | names.. | like shell's basename/dirname |
abspath | names.. | absolute path, might not exist, no follow links |
realpath | names.. | absolute path, must exist |
basename | names.. | removes suffix/extension |
suffix | names.. | extract suffix |
addsuffix | suffix,names.. | |
addprefix | prefix,names.. |
control flow
https://www.gnu.org/software/make/manual/html_node/Conditional-Syntax.html
if(n)def $(CC) if(n)eq ($(CC),gcc) else # if... endif
snippets

autogenerated help target
help: # https://blog.ovhcloud.com/pimp-my-makefile/ @grep '^[^.#]\+:\s\+.*#' Makefile | \ sed "s/\(.\+\):\s*\(.*\) #\s*\(.*\)/`printf "3[93m"``printf "3[0m"` []/" | \ expand -t20 help: # https://lobste.rs/s/7svvkz/using_bsd_make#c_mar0yk @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
set bash pipefail, use either of these
SHELL = /bin/bash -o pipefail .SHELLFLAGS = -eu -o pipefail -c
gotchas
- no support for filenames with spaces
=
assignment is perpetually evaluated$
needs to be always escaped with$$
to be sent to commands as such\t
for indentation, NOT spaces
tools
linter | checkmake unmake |
visualizer | MakefileViz makefile2graph makefile-graph |
TAP output | make2tap |
library | makext |
trivia
Why the tab in column 1?
"Yacc was new, Lex was brand new. I hadn't tried either, so I figured this would be a good excuse to learn. After getting myself snarled up with my first stab at Lex, I just did something simple with the pattern newline-tab. It worked, it stayed. And then a few weeks later I had a user population of about a dozen, most of them friends, and I didn't want to screw up my embedded base. The rest, sadly, is history." -- Stuart Feldman, from "The Art of Unix Programming"