Bruno Arine

The perfect Makefile template

Recently, I stumbled upon this Makefile template, and I can’t recall where I got this from. Funny thing is that my Makefile recipes nowadays resamble a lot with this.

.SILENT:

.PHONY: help
## This help screen
help:
	printf "Available targets\n\n"
	awk '/^[a-zA-Z\-\_0-9]+:/ { \
		helpMessage = match(lastLine, /^## (.*)/); \
		if (helpMessage) { \
			helpCommand = substr($$1, 0, index($$1, ":")-1); \
			helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
			printf "%-30s %s\n", helpCommand, helpMessage; \
		} \
	} \
	{ lastLine = $$0 }' $(MAKEFILE_LIST)

GLOBAL_VAR := "I am a global var"
GLOBAL_VAR_WITH_DEFAULT_VALUE ?= "Run 'GLOBAL_VAR_WITH_DEFAULT_VALUE=value make echo_var_with_default_value' to override this value"

.PHONY: echo_string
## A target that echoes a string literal
echo_string:
	@echo "This is a single text string"

.PHONY: echo_multiline_string
## A target that echoes a multiline string
echo_multiline_string:
	@echo "This is the first line\n" \
		"This is the second line\n" \
		"This is the third line\n"

.PHONY: install
## Install python requirments
install:
	pip install -r requirements.txt

.PHONY: freeze
## Freeze python requirments
freeze:
	pip freeze > requirements.txt

.PHONY: echo_global_var
## A target that echoes a global variable defined in the Makefile
echo_global_var:
	@echo ${GLOBAL_VAR}

.PHONY: echo_local_var
## A target that echoes a local variable
echo_local_var:
	$(eval LOCAL_VAR := 'I am a local var')
	@echo ${LOCAL_VAR}

.PHONY: echo_var_with_default_value
## A target that echoes a local variable
echo_var_with_default_value:
	@echo ${GLOBAL_VAR_WITH_DEFAULT_VALUE}

.PHONY: echo_shell_exec
## Echo the results of a shell execution assignment to a variable
echo_shell_exec:
	@echo $(shell whoami)

.PHONY: echo_env_var
## Echo the results of a shell execution
echo_env_var:
	@echo ${SHELL}

.PHONY: assign_shell_exec
## Echo the results of a shell execution assignment to a variable
assign_shell_exec:
	$(eval SHELL := $(shell echo ${SHELL}))
	@echo "Shell: ${SHELL}"

.PHONY: check_env_variable
## Check if ENV variable is defined
check_env_variable:
ifndef $(ENV_VAR)
	@echo "'ENV_VAR' is not defined. Try running 'ENV_VAR=ENV_VAR make check_env_variable'"
else
	@echo "$(ENV_VAR) is defined"
endif
	@echo "Done checking ENV_VAR"

.PHONY: curl_ip
## Echo the results of a curl GET
curl_ip:
	@echo $(shell curl -X GET 'https://checkip.amazonaws.com/')