All our projects contain a lengthy Makefile, to automate installation, build, test, and deployment. Most of the target names are standardized (make install, make deploy), but some deserve explanation (make run-dev, make restart-api). The more we add fine-grained make targets, the more we need to describe what they do in text form.
But when using the CLI, we prefer self-documenting tools. Wouldn't it better if we could just type make
, and get a list of available commands, together with their desciption?
$ make
usage : make <commands>
the following commands are available :
help Display this help
install-dev Install dependencies and prepared development configuration
install Install npm dependencies for the api, admin, and frontend apps
restart-frontend Restart the frontend and admin apps in dev
run-frontend-dev Run the frontend and admin apps in dev (using webpack-dev-server)
stop-frontend-dev Stop the frontend and admin apps in dev
It turns out it's quite easy to do. First, document each target using a comment placed after the target name, and starting with ##, as follows:
install: ## Install npm dependencies for the api, admin, and frontend apps
@echo "Installing Node dependencies"
@npm install
install-dev: install ## Install dependencies and prepared development configuration
@./node_modules/.bin/selenium-standalone install
@cp -n ./config/development.js-dist ./config/development.js | true
run-frontend-dev: webpack.PID ## Run the frontend and admin apps in dev (using webpack-dev-server)
webpack.PID:
@./node_modules/.bin/babel-node ./node_modules/.bin/webpack-dev-server \
--content-base=build \
--devtool=cheap-module-inline-source-map \
--hot \
--inline \
--progress \
& echo "$$!" > webpack.PID
stop-frontend-dev: webpack.PID ## Stop the frontend and admin apps in dev
@kill `cat $<` && rm $<
@echo "Webpack server stopped"
restart-frontend: ## Restart the frontend and admin apps in dev
@make stop-frontend-dev && make run-frontend-dev
@echo "Frontend app restarted"
Internal targets (like the webpack.PID
in our example) don't need description, and therefore don't appear in the self-documentation. Next, add a help
target in your makefile
, doing some shell scripting voodoo:
.PHONY: help
help: ## ## Display this help
@printf "\nusage : make <commands> \n\nthe following commands are available : \n\n"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'