A Better Default Makefile

A while ago I documented a robust-ish way to set up the SHELL in a Makefile.

Time has moved on and I’ve learned how to:

  • Make effective use of parallelism (so I now include MAKEFLAGS += --jobs=8 most of the time.
  • Write neater recipes using .ONESHELL
  • Implement some “standard” starter targets for Go projects:

In order to support all this, we now need to switch the shell setup based on the version of GNU Make we’re using. For some reason .ONESHELL confuses things in this regard otherwise.

You can see the most up-to-date version of this template at samsalisbury/home

Here’s how it looks at the moment:


.ONESHELL:
# Make on macOS is stuck at 3.81
ifeq ($(MAKE_VERSION),3.81)
	SHELL := /usr/bin/env bash -euo pipefail -c
else
	SHELL := /usr/bin/env
	.SHELLFLAGS = -euo pipefail -c
endif
MAKEFLAGS += --silent --jobs=8
QUIET_UNLESS_FAIL = OUT="$$($2 2>&1)" || { CODE="$$?"; printf "$1 failed:\n%s" "$$OUT"; exit $$CODE; }; echo "$1: OK"
default: test
.PHONY: default
# -----
# Section: Go General
# This section should be useful for all go projects.
# -----
ALL_PACKAGES := ./...
compile:
	$(call QUIET_UNLESS_FAIL,Compilation, go build $(ALL_PACKAGES))
	$(call QUIET_UNLESS_FAIL,Test compilation, go test -exec true $(ALL_PACKAGES))
.PHONY: compile
test: compile
	$(call QUIET_UNLESS_FAIL,Running go tests, go test $(ALL_PACKAGES))
.PHONY: test
# -----
# Section: Go Executable.
# This section is useful for go projects creating an executable.
# -----
NAME := hc-gh
# BIN is the binary name.
BIN  := ./$(NAME)
# DESTDIR is the absolute path to the install path if running 'make install'
# Default to wherever it's currently installed using which, or /usr/local/bin
# if it's not yet installed.
DESTDIR ?= $(shell $$(dirname $$(which $(NAME)) 2>/dev/null || echo /usr/local/bin)
build: $(BIN)
	echo $<
.PHONY: build
$(BIN): test
	go build -o "$@"
.PHONY: $(BIN)
install: $(BIN)
	mkdir -p "$(DESTDIR)"
	install "$(BIN)" "$(DESTDIR)"
.PHONY: install

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: