Makefile help target

This is a small hacky snippet showing how to display help for targets

Makefile help target
Photo by freestocks / Unsplash

It's quite controversial to use make as a local command runner. Nevertheless a lot of projects are using it that way as the binary is almost omnipresent and the friction using it is quite small. This blog post shows a target for displaying help for other targets in a ... helpful way.

Note: It's a hack!

A basic Makefile is taken for illustration. It contains two targets that just print something:

.PHONY: up
up:
	@echo "Running up"

.PHONY: down
down:
	@echo "Running down"
The .PHONY: is there to ignore any files of the same name as make targets are usually executing files if present.

When running make up you will see printed

$ make up
Running up

$ 

But how can you list all targets of a Makefile? Short answer is not. There is no way to list all defined targets builtin. There is builtin autocomplete though.

Also it sometimes it would be nice to have a short description alongside the target to see what it does.

Wouldn't it be nice to have some output like

 Targets for the Makefile

 General
 -------

 help           Print commands help.
 up             Print "Running up".
 down           Print "Running down".

when running make or make help?

In order to achieve this there are two things you need.

First is to insert the help comments into the Makefile. The file will be parsed (see below) and therefore needs some structure to make sense.

The way chosen here is to have special comment that start with two #. Those are the help related ones. F.e.

## up		Print "Running up".
.PHONY: up
up:
	@echo "Running up"

This will then print the line up Print "Running up"..

Second part is to have the help target which parses the comments. This target looks like this:

help: Makefile
	@sed -n 's/^##//p' $<

As a quick explainer: The target takes the Makefile and runs the sed command on it's contents returning the parsed results. This looks admittedly very arcane because it is (note it's a hack).

The complete example printing the output from above then looks something like this:

default: help

## Targets for the Makefile

##
## General
## -------
##

## help		Print commands help.
.PHONY: help
help: Makefile
	@sed -n 's/^##//p' $<


## up		Print "Running up".
.PHONY: up
up:
	@echo "Running up"

## down		Print "Running down".
.PHONY: down
down:
	@echo "Running down"

This allows you to either run make or make help to have the help being printed.

The default: marks the default target. If help is your first target you can omit it as make without arguments always takes the first target.