What should I make?

Published Aug 6, 2021

I noticed a cool pattern at work recently: all of our Makefiles have a help target. Running make help prints out all targets and includes any trailing comment on the same line. And that solves essentially the only problem I’ve found with using make as a simple task runner: Is this a verb-noun or noun-verb project? So I took a random Makefile I had lying around at home and tried to make it self-documenting.

When I started, my work laptop was in another room and the internet was, like, right here, so I searched “self-documenting makefile” and found Self-Documented Makefile which helped me learn about MAKEFILE_LIST. Clearly, I’m far from the first person to do this, but I think I’ve made some interesting improvements!

Anyway, here’s the thing:

.PHONY: help
help: ## List targets in this Makefile
	@awk '\
		BEGIN { FS = ":$$|:[^#]+|:.*?## "; OFS="\t" }; \
		/^[0-9a-zA-Z_-]+?:/ { print $$1, $$2 } \
		| sort --dictionary-order \
		| column --separator $$'\t' --table --table-wrap 2 --output-separator '    '

Document targets with end-of-line double-hash comments (##):

.PHONY: clean
clean: ## Remove output files
	rm -rf dist

.PHONY: release
release: clean ## Build app in release mode
	npm install
	npm run build

And example output:

clean           Remove output files
help            List targets in this Makefile
release         Build app in release mode

Features I kept:

  • Non-doc comments can still be made with single-hashes.
  • Running just make is equivalent to make help. But TIL .DEFAULT_GOAL is a GNU make extension.

Things I changed:

  • Don’t skip targets without documentation. There’s not often a lot to say about make build, but it’s still nice to know it’s there.
  • In case you forget what make help does, it tells you. 😛
  • Look, no grep! I finally get to show off what I learned by reading Awk in 20 Minutes.
  • I recently learned that sort orders some characters differently by default on MacOS from my normal Linux setup (BSD vs. GNU?) (also 🙁), so I tried to make that more consistent. I think the Makefile grammar makes it impossible to trigger that difference, but I’m not taking any chances!
  • I like tabular output but hate adjusting spacing. I don’t actually care about portability, so column works great!