patternMinor
Built-in help in a Makefile
Viewed 0 times
builtmakefilehelp
Problem
My colleagues often ask me, "Dude could you remind me what I have to type to build this target?". So I eventually implemented a nice workaround in my Makefiles.
I wanted my Makefiles to have a help target that give some usage clues to the users. This is achieved with an embedded Perl script and some markers.
Wherever I want a target to be documented, I simply add this trailing comment:
Here is an example:
Here what I get if I type
In the case the Makefile takes time to parse the dependencies we can bypass the file for the
What do you think of this technique. Is it a good approach? Can I improve it?
I wanted my Makefiles to have a help target that give some usage clues to the users. This is achieved with an embedded Perl script and some markers.
Wherever I want a target to be documented, I simply add this trailing comment:
##@ Here is an example:
SCRIPT_VERSION=v1.0
SCRIPT_AUTHOR=John Doe
all: ##@Build Build all the project
echo "Hello World!" > all
clean: ##@Cleaning Remove all intermediate objects
rm all
mrproper: clean ##@Cleaning Remove all output and interemediate objects
HELP_FUN = \
%help; while(<>){push@{$help{$2//'options'}},[$1,$3] \
if/^(\w+)\s*:.*\#\#(?:@(\w+))?\s(.*)$/}; \
print"$_:\n", map" $_->[0]".(" "x(20-length($_->[0])))."$_->[1]\n",\
@{$help{$_}},"\n" for keys %help; \
help: ##@Miscellaneous Show this help
@echo -e "Usage: make [target] ...\n"
@perl -e '$(HELP_FUN)' $(MAKEFILE_LIST)
@echo -e "Written by $(SCRIPT_AUTHOR), version $(SCRIPT_VERSION)"
@echo -e "Please report any bug or error to the author."Here what I get if I type
make help:$ make help
Usage: make [target] ...
Miscellaneous:
help Show this help
Build:
all Build all the project
Cleaning:
clean Remove all intermediate objects
mrproper Remove all output and interemediate objects
Written by John Doe, version v1.0
Please report any bug or error to the author.In the case the Makefile takes time to parse the dependencies we can bypass the file for the
help target: ifeq (,$(filter help,$(MAKECMDGOALS)))
# Core of the makefile
endifWhat do you think of this technique. Is it a good approach? Can I improve it?
Solution
It looks pretty good to me, but I see a few minor things that might be improved.
Specify which
I'd recommend not leaving it to chance as to which instance of
Allow multiword category tags
With a slight change in your regex, multiword categories could be supported. If the second line is changed to this:
It will support multiword categories, delimited with
Sort the keys for printing
On my machine, I get a different ordering each time I run
Note that you shouldn't have a line continuation there, and you don't need the trailing semicolon (although you may prefer one for style reasons).
Omit declaration of hash
Because
Specify which
perl to runI'd recommend not leaving it to chance as to which instance of
perl is run. Instead, for both safety and consistency, it might be better to do this:PERL=/usr/bin/perl
##...
@$(PERL) -e '$(HELP_FUN)' $(MAKEFILE_LIST)Allow multiword category tags
With a slight change in your regex, multiword categories could be supported. If the second line is changed to this:
if/^(\w+)\s*:.*\#\#(?:@([^@]*)@)?\s(.*)$/}; \It will support multiword categories, delimited with
@, nothing: ##@Odds & ends@ Do nothing, but gracefullySort the keys for printing
On my machine, I get a different ordering each time I run
make help which is a little confusing. To fix that, sort the keys, rendering the last line:@{$help{$_}},"\n" for sort keys %helpNote that you shouldn't have a line continuation there, and you don't need the trailing semicolon (although you may prefer one for style reasons).
Omit declaration of hash
Because
%help is unambiguously used, you don't need to predeclare it. It will automatically be created as an empty hash, so the first line can become:while(<>){push@{$help{$2//'options'}},[$1,$3] \Code Snippets
PERL=/usr/bin/perl
##...
@$(PERL) -e '$(HELP_FUN)' $(MAKEFILE_LIST)if/^(\w+)\s*:.*\#\#(?:@([^@]*)@)?\s(.*)$$/}; \nothing: ##@Odds & ends@ Do nothing, but gracefully@{$$help{$$_}},"\n" for sort keys %helpwhile(<>){push@{$$help{$$2//'options'}},[$$1,$$3] \Context
StackExchange Code Review Q#94307, answer score: 5
Revisions (0)
No revisions yet.