Skip to content

Documenting Makefiles#

After having spent years documenting my Makefiles using (a variation of) this awk one-liner, I decided to factor things out in a library makefile-doc. This turned out to be a nice small project with awk. The following is a short overview.

As an example, consider the documentation of the Makefile (at tag v1.4) of makefile-doc:

-----------------------
Available targets:
-----------------------
help            Show this help
test            Run integration tests
utest           Run unit tests
test-all        Run integration tests with all supported awk variants
utest-all       Run unit tests with all supported awk variants
coverage.html   Run integration/unit tests with goawk and generate a coverage report
lint            Lint the code using gawk
clean-bin       Remove all downloaded awk variants
clean           Remove coverage reports
release         Create github release at latest tag

------ Individual integration tests ------

test-           Recipes:
                ---------
                backslash-comments
                backslash-recipe
                backticks
                default
                deprecated
                ...

-----------------------
Command-line arguments:
-----------------------
AWK             Supported awk variants: {awk, mawk, nawk, bawk, wak, goawk}
OUTPUT_FORMAT   {ansi, html}
UPDATE_RECIPE   If set, the expected value of a test recipe is updated
                e.g., make test-default UPDATE_RECIPE=1
-----------------------

I find it useful to document both targets and variables. This can be done using ##, ##! and ##% placed either above them or inline1. The syntax is:

##% A variable
VAR := 1

## Top-level docs take precedense
## and could stretch over multiple lines
t1: ## This is not shown

##@ This defines a section

t2: ##! This is the doc for t2

Explicitly listing (in an automated way) the possible values for command-line arguments is helpful. For example, currently there are 6 supported variants of awk as can be seen from the documentation of the command-line argument AWK. In a simmilar manner one can see how individual tests can be run, using make test- followed by a particular recipe (the number of entries and their formatting can be specified using several parameters).

To use makefile-doc, simply place the following at the top of your Makefile (for more details see the project README):

help: URL := github.com/drdv/makefile-doc/releases/latest/download/makefile-doc.awk
help: DIR := $(HOME)/.local/share/makefile-doc
help: SCR := $(DIR)/makefile-doc.awk
help: ## show this help
    @test -f $(SCR) || wget -q -P $(DIR) $(URL)
    @awk $(VFLAGS) -f $(SCR) $(MAKEFILE_LIST)

The variable VFLAGS can be left empty or can be used to pass options to the makefile-doc.awk script via the standard -v OPTION=VALUE flag of awk. This is pretty much it, the rest is exploring some of the options and finding what works for you. As an example, the project's Makefile uses the following options:

help: VFLAGS := \
    -v SUB='$(TESTS_SUB);$(AWK_SUB)' \
    -v EXPORT_THEME=$(EXPORT_THEME) \
    -v COLOR_BACKTICKS=33 \
    -v OUTPUT_FORMAT=$(OUTPUT_FORMAT)`

The above HTML docs have been generated using make OUTPUT_FORMAT=HTML (output to Latex is supported as well).

Substitutions#

The SUB option specifies substitutions and value formatting. For example, the listing of the supported awk variants is generated using

AWK_SUB := <L:0,M:0,I:{,T:},S:\\,>AWK:$(SUPPORTED_AWK_VARIANTS)

The actual values come from the variable $(SUPPORTED_AWK_VARIANTS), while the following parameters control the formatting:

  • L:0 - list the values starting from the current line
  • M:0 - list the values on a single line (as opposed to M:1 for multi-line listing)
  • I:{ and T:} define the initial and terminal delimiters
  • S:\\, is the separator (note that the comma has to be escaped).

The format of a substitution is [<p1:v1,...>]NAME[:LABEL]:[VALUES]. For the above example we have:

  • [<p1:v1,...>] <L:0,M:0,I:{,T:},S:\\,>
  • NAME AWK
  • [VALUES] $(SUPPORTED_AWK_VARIANTS).

Only the optional [:LABEL] is omitted. It is normally used to rename targets specified in terms of variables -- as is the case with the individual test targets above (where [:LABEL] test- because the actual target name is $(TESTS): and it is not very informative at the level of the documentation).

Theme#

The default Solarized theme can be easily customised. Below is an example of the same Makefile but using the Dracula theme and exported to png2. Unlike the HTML version above (where the background is left to be transparent), here we have set a black background. A "standalone" image is generated for convenient use in presentations.

ss


  1. The meaning of the three tokens is entirely up to you. 

  2. This is done by specifying the EXPORT_THEME option (see the project README.)