Skip to content

Instantly share code, notes, and snippets.

@prwhite
Last active May 13, 2026 11:45
Show Gist options
  • Select an option

  • Save prwhite/8168133 to your computer and use it in GitHub Desktop.

Select an option

Save prwhite/8168133 to your computer and use it in GitHub Desktop.
Add a help target to a Makefile that will allow all targets to be self documenting
# Add the following 'help' target to your Makefile
# And add help text after each target name starting with '\#\#'
help: ## Show this help.
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
# Everything below is an example
target00: ## This message will show up when typing 'make help'
@echo does nothing
target01: ## This message will also show up when typing 'make help'
@echo does something
# Remember that targets can have multiple entries (if your target specifications are very long, etc.)
target02: ## This message will show up too!!!
target02: target00 target01
@echo does even more
@Windowsfreak
Copy link
Copy Markdown

I tried @BlackHole1 's solution and got this :(

Usage: make <command>
awk: illegal statement
 input record number 1, file 
 source line number 1```

@BlackHole1
Copy link
Copy Markdown

BlackHole1 commented Oct 23, 2023

I tried @BlackHole1 's solution and got this :(

Usage: make <command>
awk: illegal statement
 input record number 1, file 
 source line number 1```

@Windowsfreak Can you share the contents of your makefile? It works fine on my local machine.

@BlackHole1
Copy link
Copy Markdown

@Windowsfreak I just reproduced this issue on macOS. you need to install gawk first (brew install gawk).

AWK := awk
ifeq ($(shell uname -s), Darwin)
	AWK = gawk
    ifeq (, $(shell which gawk 2> /dev/null))
        $(error "gawk not found")
    endif
endif
-	@grep -F -h "##@" $(MAKEFILE_LIST) | grep -F -v grep -F | sed -e 's/\\$$//' | awk 'BEGIN {FS = ":*[[:space:]]*##@[[:space:]]*"}; \
+ 	@grep -F -h "##@" $(MAKEFILE_LIST) | grep -F -v grep -F | sed -e 's/\\$$//' | $(AWK) 'BEGIN {FS = ":*[[:space:]]*##@[[:space:]]*"}; \

Full Code:

AWK := awk
ifeq ($(shell uname -s), Darwin)
	AWK = gawk
    ifeq (, $(shell which gawk 2> /dev/null))
        $(error "gawk not found")
    endif
endif

##@
##@ Clean build files commands
##@

kernel-%-clean: ##@ Clean kernel build files with specified architecture
                ##@ e.g. kernel-amd64-clean / kernel-arm64-clean
	$(MAKE) -C ./arch/kernel/$* clean

rootfs-%-clean: ##@ Clean rootfs build files with specified architecture
                ##@ e.g. rootfs-amd64-clean / rootfs-arm64-clean
	$(MAKE) -C ./arch/rootfs/$* clean

clean: ##@ Clean all build files
	$(MAKE) kernel-amd64-clean
	$(MAKE) kernel-arm64-clean
	$(MAKE) rootfs-amd64-clean
	$(MAKE) rootfs-arm64-clean

##@
##@ Misc commands
##@

help: ##@ (Default) Print listing of key targets with their descriptions
	@printf "\nUsage: make <command>\n"
	@grep -F -h "##@" $(MAKEFILE_LIST) | grep -F -v grep -F | sed -e 's/\\$$//' | $(AWK) 'BEGIN {FS = ":*[[:space:]]*##@[[:space:]]*"}; \
	{ \
		if($$2 == "") \
			pass; \
		else if($$0 ~ /^#/) \
			printf "\n%s\n", $$2; \
		else if($$1 == "") \
			printf "     %-20s%s\n", "", $$2; \
		else \
			printf "\n    \033[34m%-20s\033[0m %s\n", $$1, $$2; \
	}'

@jaymecd
Copy link
Copy Markdown

jaymecd commented Oct 30, 2023

@Windowsfreak @BlackHole1 no need for gawk, just replace pass with empty printf and problem solved. BSD awk does not know pass command.

		if($$2 == "") \
-			pass; \
+			printf ""; \
$ PATH="/usr/bin:/usr/sbin:/bin:/sbin" make help

Usage: make <command>

Clean build files commands

    kernel-%-clean       Clean kernel build files with specified architecture
                         e.g. kernel-amd64-clean / kernel-arm64-clean

    rootfs-%-clean       Clean rootfs build files with specified architecture
                         e.g. rootfs-amd64-clean / rootfs-arm64-clean

    clean                Clean all build files

Misc commands

    help                 (Default) Print listing of key targets with their descriptions

@kjellericson
Copy link
Copy Markdown

Many good suggestions.
I felt the help syntax a bit ugly when having several target dependancies.
99% of my targets are non-files, and therefor PHONY targets. So I put the check on the PHONY targets only.

This doesn't fit everyone, but maybe gives some one some thougths.

PHONY: help ## Show this help.
help:
	@grep -he '^PHONY:.*##' $(MAKEFILE_LIST) | sed -e 's/ *##/:\t/' | sed -e 's/^PHONY: *//'

I think writing a "makefile-helper <makefile_list>" in perl will be my next approach. I got many Makefiles, and copy/paste any advanced script into each Makefile is just bad.

@adepretis
Copy link
Copy Markdown

@kjellericson you could use include /absolute/or/relative/path/to/*.mk instead of embedding it into each Makefile directly.

@chrissv
Copy link
Copy Markdown

chrissv commented Feb 28, 2024

Hi, just discovered this gist/conversation from a google search. The solution by @BlackHole1 (Oct 26, 2023) meets my needs 90%.
But in some of our makefiles we have a dependency after the target, like this:

app: $(APP_FILE2).exe $(APP_FILE2).exe ##@ Build the applications

The items after the ":" are displayed in the help, and I really don't want this.

I am not conversant enough in awk/gawk to figure out how to suppress the display of the items after the ":"
Can anyone give me advice?

Thanks!

@letrunghieu
Copy link
Copy Markdown

Hi @chrissv, you can repeat the target twice. Once for the help comment and the other one for the list of dependencies. With your example:

app: ##@ Build the applications
app: $(APP_FILE2).exe $(APP_FILE2).exe

@chrissv
Copy link
Copy Markdown

chrissv commented Apr 4, 2024

Hi @chrissv, you can repeat the target twice. Once for the help comment and the other one for the list of dependencies. With your example:

app: ##@ Build the applications
app: $(APP_FILE2).exe $(APP_FILE2).exe

That's a great suggestion, thanks!

@drdv
Copy link
Copy Markdown

drdv commented Dec 23, 2024

I find it difficult to maintain awk one liners across various makefiles. This is a version organised in a script.

@Wotanihor
Copy link
Copy Markdown

When you are always on the go, you often have to review documents or articles straight from your smartphone. Not all checking websites are optimized for mobile screens, which slows down workflow. I find it very convenient to use a dedicated brisk AI detector app instead. You can quickly copy text from your emails and instantly know if it was written by a chatbot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment