DEV Community

Kathryn DiPippo
Kathryn DiPippo

Posted on • Updated on

How to configure Makefile to dynamically generate list of commands

In past projects I've worked on, the first command inside the Makefile was always a manually maintained list of commands available in the file:

.PHONY: list command-one command-two

list:
    @echo "command-one    This command performs A, B, and C"
    @echo "command-two    This command performs X, Y, and Z"

command-one:
    @echo "Example command"

command-two:
    @echo "Example command"
Enter fullscreen mode Exit fullscreen mode

But thanks to the Makefile set up in this Python starter project, there's an even handier way to have make list shown above be generated without updating two places.

How it works

At the top of the Makefile

.PHONY: help
help:             ## Show the help.
    @echo "Usage: make <target>"
    @echo ""
    @echo "Targets:"
    @fgrep "##" Makefile | fgrep -v fgrep
Enter fullscreen mode Exit fullscreen mode

The fgrep here is the key, where the Makefile itself is parsed for any comments prefixed with ## and printing the entire lines. Any comments with just one # will be ignored. With the help command itself, the second line is what is fgrep-ed and printed.

Full example

.PHONY: help
help:             ## Show the help.
    @echo "Usage: make <target>"
    @echo ""
    @echo "Targets:"
    @fgrep "##" Makefile | fgrep -v fgrep

.PHONY: command-one
command-one:      ## This command performs A, B, and C
    @echo "Example command"
    # Inner comment to describe script.
    @echo "run shell script"

.PHONY: command-two
command-two:      ## This command performs X, Y, and Z
    @echo "Example command"

.PHONY: command-hidden
command-hidden:   # This command performs initialization
    @echo "Example hidden command"
Enter fullscreen mode Exit fullscreen mode

The results of running make or make help:

Usage: make <target>

Targets:
help:             ## Show the help.
command-one:      ## This command performs A, B, and C
command-two:      ## This command performs X, Y, and Z
Enter fullscreen mode Exit fullscreen mode

Note: for commands with dependencies to others, I found it useful to instead copy the command for the comment line and then have a second line for the dependencies, i.e.:

.PHONY: command-two
command-two:      ## This command performs X, Y, and Z
command-two: clean build
    @echo "Example requires 'make clean' & 'make build'"
Enter fullscreen mode Exit fullscreen mode

Thought this was a really interesting configuration and wanted to share. Hope you find it useful too!

Top comments (0)