make

Make is a powerful build system with the simple concept of transforming files in other files based on a recipe

flowchart LR A[source files] B(( recipe )) C[output files] A --> B --> C

Special chars

The makefile syntax involves some character that expands to specific files when make is executed, such as:

makefile vars

A var in a makefile is defined as follows:

BUILDDIR = ./build

And is referred with the $() notations

mytarget:
  some_long_command $(BUILDDIR)

✔️ ENVIRONMENT variables are automatic exposed with the same notation $(), example $(HOME)

Also to notice that target indentation is independent from the Makefile one, for example:

do_something:
ifeq ($(app),)
  $(error app is not set)
endif
  ./do_something.sh  $(app)

⚠️ Warning

The indentation of the command is mandatory and must be a tab character, while the indentation of the rest of the file is not relevant

PHONY targets

Phony targets are targets that doesn’t generate any file, they are a useful way to group other targets together

.PHONY: build clean

Examples

BUILDDIR = ./build

%.png: %.mmd
	mkdir -p $(BUILDDIR)
	mmdc -i $< -o $(BUILDDIR)/$@

clean:
	rm -rf $(BUILDDIR)

build: $(patsubst %.mmd,%.png,$(wildcard *.mmd))

Defining dynamic make help messages

This target parses @# Help: comments and prints them side by side with target names

help:
  @printf "%-40s %s\n" "Target" "Description"
  @printf "%-40s %s\n" "------" "-----------"
  @make -pqR : 2>/dev/null \
      | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' \
      | sort \
      | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' \
      | xargs -I _ sh -c 'printf "%-40s " _; make _ -nB | (grep -i "^# Help:" || echo "") | tail -1 | sed "s/^# Help: //g"'