GNU Makefile template

Template for writing a new GNU Makefile

My GNUmakefile template, with inspiration from:

As with all formulae, I may update this from time to time.

GNUmakefile vs Makefile

I prefer to use GNUmakefile as the filename to emphasize that this will not work with other make implementations.

GNU make will look for a Makefile if GNUmakefile is not present, so you can use that name instead if you prefer.

Take care: GNU make looks for Makefile (capital M) or GNUmakefile (lower-case m).

Template

Available directly at GNUmakefile (shortened).

# -*- mode: Makefile -*-

# A portable, self-documenting GNU Makefile for projects
#
# Suitable for projects where you write the Makefile by hand.
#
# Notes:
# - ".PHONY" targets do not generate files
# - Targets without .PHONY are assumed to generate files
# - See the help comment, after '##', for each target
# - For targets that do not have a '## comment', they are not shown in the help output
# - The help target is the first target, so it's also what gets run if you just run 'make' without a target

# Ignore built-in inference rules that determine eg how to build object files from C source code.
# You might not want this if you're writing a Makefile for a C project.
.SUFFIXES:

# Warn if any variables are undefined.
MAKEFLAGS += --warn-undefined-variables

# Fail if any command fails.
# Note that just because we're using GNU Make doesn't mean we're using Bash.
.SHELLFLAGS := -eu

# Show a nice table of Make targets.
# Generate it by grepping through the Makefile for targets with a ## after them,
# and treat everything following ## as the description.
.PHONY: help
help: ## Show this help
	@egrep -h '\s##\s' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'

.PHONY: exsetenv
exsetenv: export FOO := "BAR"
exsetenv: export BAZ := ${BAT}
exsetenv: ## An example that involves setting an env var for the command
    some-command ...

.PHONY: exdep1
exdep1:
    do something ...

# This target depends on exdep1, which is .PHONY, so it runs it every time
.PHONY: exdepend
exdepend: exdep1
    do something ...

build/generated.txt:
    mkdir -p build/
    echo "asdf" > build/generated.txt

# This target depends on the previous one, which is not .PHONY,
# which means it only reruns the previous target if necessary
# (helpful if building the previous target is time-intensive)
.PHONY: usegeneratedtxt
usegeneratedtxt: ## Show an example file that was generated in a different step
    cat build/generated.txt

.PHONY: example-ripgrep
example-ripgrep: ## Run a command over the codebase to search for something
	rg "search-term"

.PHONY: example-script
example-script: ## Run a script that is saved to the scripts/ directory
	scripts/exscript asdf

Requires GNU Make

Unlike my shell script formulae, I require GNU Make rather than trying to stick with POSIX.