Makefile

Created: 17 Dec 2020
Updated: 17 Jan 2025
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

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
  • 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

%:     ; $(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)
    1. cli
    2. makefile
    3. environment
    4. 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

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..  

gotchas

  • = assignment is perpetually evaluated
  • $ needs to be always escaped with $$ to be sent to commands as such
  • \t for indentation, NOT spaces