Skip to content

Instantly share code, notes, and snippets.

@vlaci
Last active January 13, 2021 17:44
Show Gist options
  • Save vlaci/304110986bad60ac87513b189503e21a to your computer and use it in GitHub Desktop.
Save vlaci/304110986bad60ac87513b189503e21a to your computer and use it in GitHub Desktop.
Makefile template with colorful help target (requires gawk)
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
# In jurisdictions that recognize copyright laws, the author or authors
# of this software dedicate any and all copyright interest in the
# software to the public domain. We make this dedication for the benefit
# of the public at large and to the detriment of our heirs and
# successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# For more information, please refer to <http://unlicense.org/>
.ONESHELL:
SHELL = bash
.SHELLFLAGS = -euo pipefail -c
.DEFAULT_GOAL :=
BOLD = \033[1m
GREEN = \033[32m
YELLOW = \033[33m
RESET = \033[0m
###############################################################################
## General
.PHONY: help
help: ## Show this help message
#
# Parses help message from Makefile. Messages must appear after target or
# variable specification. Description must start with at least one whitespace
# character and followed by `##` characters. If global variables section is not
# needed, remove or comment out its section.
#
# Suggested Makefile layout:
# GLOBAL_VARIABLES ?= dummy ## Global variables
# PRIVATE_VARIABLE ?= private # No help shown here
# ...
#
# ## Section header
# help: ## Show this help message
# ...
#
# ## Another section
# target: ## Shows target description
# ...
# target: TARGET_SPECIFIC ?= ## This description appears at target's help
#
ifeq (, $(shell which gawk))
@echo -e "$(RED)This target requires 'gawk'. Install that first.$(RESET)" && exit 1
endif
@echo -e "Usage: $(BOLD)make$(RESET) $(YELLOW)<target>$(RESET) [$(GREEN)VARIABLE$(RESET)=value, ...]"
@echo
@echo -e "$(BOLD)Global variables:$(RESET)"
gawk 'match($$0, /^## (.+)$$/, m) {
printf "\n$(BOLD)%s targets:$(RESET)\n", m[1]
}
match($$0, /^([^: ]+)\s*:\s*[^#=]+## +(.*)/, m) {
if (length(m[1]) < 10) {
printf " $(YELLOW)%-10s$(RESET) %s\n", m[1], m[2]
} else {
printf " $(YELLOW)%s$(RESET)\n%-12s %s\n", m[1], "", m[2]
}
}
match($$0, /^([^?= ]+)\s*\?=\s*([^# ]+)?\s*## +(.*)/, m) {
if (length(m[2]) == 0) {
m[2] = "unset"
}
printf " $(GREEN)%s$(RESET): %s (default: $(BOLD)%s$(RESET))\n", m[1], m[3], m[2]
}
match($$0, /^[^: ]+\s*:\s*([^?= ]+)\s*\?=\s*([^# ]+)?\s*## +(.*)/, m) {
if (length(m[2]) == 0) {
m[2] = "unset"
}
printf "%-13s- $(GREEN)%s$(RESET): %s (default: $(BOLD)%s$(RESET))\n", "", m[1], m[3], m[2]
}
' $(MAKEFILE_LIST)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment