Makefiles are convenient for semi-automating project tasks. We often use these files for running, building, and deploying projects. However, they often come without documentation.

This article explains how to print Makefile targets to the command line with help texts.

The self-documented Makefile

Many years ago, François Zaninotto wrote an article called Self-Documented Makefile, where he introduces a nifty little script that allows us to provide help texts to each directive.

Zaninotto’s help directive has been a staple in my projects for years, and today I want to share it with you.

Below, I will provide a snippet and explanation of the help directive and how I use it. I am not an expert on this technology, and recommend you also check out the original article for an expanded breakdown.

Basic setup

Here’s our example Makefile:

# Developer note:
#
# Run `make` or `make help` to display a list of targets and help texts.
#
# If you add a new command, add a help text by adding a comment on the same
# line as the target name. You should use the following structure:
# `<target name>:  ## <help text>`
#
# See also:
# https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html

.PHONY: help
.DEFAULT_GOAL := help

help:  ## Shows available Makefile targets in a list
    @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

Let’s break this file down:

First, the file explains the help directive and the help text syntax. The documentation also links to the original author’s blog post.

Following the documentation, you’ll find some settings.

The .PHONY setting tells Make to run the help target as a command instead of looking for a file of the same name to use.

The .DEFAULT_GOAL setting tells Make to run this directive if the user runs the make command without arguments.

Note: Make runs the first target it finds by default, so setting the default goal is superfluous if you keep help on top. I prefer to add the configuration anyway since it’s more explicit.

Following the documentation, you’ll find the help target itself. I copied the command from the original author’s blog post verbatim.

Example

Let’s take this help command for a spin. Add any directive you want to the Makefile; I’ll use hello for this example:

# ...
.PHONY: help hello
# ...

hello:  ## Say hello to the world
    echo "Hello world!"

Now run the Make command, and observe its outcome:

# You can also run `make` as-is thanks to `.DEFAULT_GOAL`
$ make help
# hello                          Say hello to the world
# help                           Shows available Makefile targets in a list

Handy! The help outcome lists all targets with an explanation text in alphabetical order. The command ignores all targets without help text.

Note for the copy/pasters

My blog converts all code indentations to spaces. However, Makefiles only accept tabs as indentation. Make sure you replace all four-space indents with single tabs!

Wrap-up

Spice up your Makefile with help texts in the same file. The help command lists all available targets with help texts, so you can see them without opening the file!

Again, major credit to François Zaninotto and his original article. If you haven’t done so already, find the link at the top of this article and check it out!