wiki | https://en.wikipedia.org/wiki/Make_(software) |
gnu make | https://www.gnu.org/software/make/ |
posix make | https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html |
fork | https://justine.lol/make/ |
alternative | https://github.com/casey/just |
alternative | https://taskfile.dev/ |
alternative | https://snakemake.github.io/ |
manual | https://www.gnu.org/software/make/manual/html_node/index.html |
- 1976
- Author: Stuart Feldman
- library: https://github.com/mitjafelicijan/makext
- tool: linter https://github.com/mrtazz/checkmake
cli
make [-f Makefile] [VAR="foo"] [OPTIONS] [TARGETS]
-f=MAKEF | (make)file=MAKEFILE | |
-o TARGET | 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 N | jobs=N | parallel jobs |
-n | dry-run | |
-t | touch | touch targets, without running |
-d | –debug=[a¦b¦v¦i¦j¦m¦n] | print debug |
warn-undefined-variables | when referenced | |
-r | no-builtin-rules | |
-R | no-builtin-variables |
language
- defines a dependency tree of
rules
(aka recipe)- made of
targets
(the vertex) - final exe is the root vertex
- made of
- bare "make" run defaults to the first target
- can be more than 1 target
- fails if a command returns 1
- 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
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 | set it to "bash" to change default shell |
MAKE_FLAGS | |
.SHELLFLAGS | set it to "-eu -o pipefail -c" for "bash" |
.RECIPEPREFIX | use instead of tabs |
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
gotchas
=
assignment is perpetually evaluated$
needs to be always escaped with$$
to be sent to commands as such\t
for indentation, NOT spaces