This replaces an earlier Perl version I'd been using for years, but I started thinking, hey, Bash can do all that. It's about ten lines longer than the Perl version, but possibly more readable.
GIST=https://gist.githubusercontent.com/ernstki/982edcfbf93c357bdb09878f7c724389
THING=raw/Makefile_with_built_in_help
(set -x; curl -sL $GIST/$THING || wget -qO- $GIST/$THING) > MakefileAdd your targets after the provided help target, because they'll be printed in the order they appear in the file, not sorted. (Although if you wanted them sorted, to implement that would be straightforward.) Shove that bunch of Bash script to the bottom of the file and forget about it.
If you want help for a target, put a comment after it, on the same line, like this:
# ⋮
help: # prints this help
@bash -c "$$AUTOGEN_HELP_BASH" < $(ME)
build: dep1 dep2 # build all the things
build-the-thing $<
# ⋮Then run make help or just make (as long as you leave it at the top, it's the default target). Easy peasy.
If you don't want a target to appear in the output of make help, don't put a comment on the same line as the target name:
# this target won't show up in the output of 'make help'
dep1: dep3
do-the-other-thing $< > $@Put your comment above or below instead, if you need to document it internally.
If you wanted, for example, build to be the default target instead of help, use .DEFAULT_GOAL for that:
# ⋮
.DEFAULT_GOAL = build
help: # prints this help
@bash -c "$$AUTOGEN_HELP_BASH" < $(ME)
build: dep1 dep2 # build the things
whatever-build-thing --arg1 --arg2 $<
# ⋮The regexp is supposed to ignore any dependencies for the target, and it's a bug if it doesn't.
As written, would not support multiple targets in a single rule.
There are double quotes in the definition of AUTOGEN_HELP_BASH, which is itself double-quoted when passed to bash -c. Frankly I'm astonished that this worked. I suppose Make itself is taking care of the escaping under the hood, but I still have a feeling that somewhere this will eventually go wrong, and require some more attention. If you get in some kind of trouble with this, as long as the quotes are only for display purposes, just use curly quotes instead; e.g.
Option+{
for a US keyboard layout on macOS, or,
RAlt+Shift+<, Shift+'
assuming RAlt is your Compose key on Linux.
Feedback welcome.
