Modernizing Make
Whether you’re actually utilizing Make’s build capabilities, or simply using it to run ad-hoc “tasks”, Make is a ubiquitous tool used across the industry, but can we improve upon it without starting from scratch?
MMake or “Modern Make” is a small Go program wrapping standard Make to augment its functionality, providing nice help output, remote inclusion, and possibly more in the future.
Help output
The first small feature is first-class target help output. Suppose you have the following makefile with a few targets defined, you’d like to have a way to view the help from the command-line right?
# Start the dev server.
#
# Note that the API must also be running.
start:
@gopherjs -m -v serve --http :3000 github.com/tj/docs/client
.PHONY: start# Start the API server.
api:
@go run server/cmd/api/api.go
.PHONY: api# Display dependency graph.
deps:
@godepgraph github.com/tj/docs/client | dot -Tsvg | browser
.PHONY: deps# Display size of dependencies.
size:
@gopherjs build client/*.go -m -o /tmp/out.js
@du -h /tmp/out.js
@gopher-count /tmp/out.js | sort -nr
.PHONY: size
With make aliased to mmake you can simply run make help
:
start Start the dev server.
api Start the API server.
deps Display dependency graph.
size Display size of dependencies.
Alternatively you may view the full description for a single target via make help start
:
Start the dev server.Note that the API must be also running.
Remote includes
The second feature currently supported is recursive remote includes, which are stored in /usr/local/include providing backwards-compatible support for users without mmake installed.
For example to extract some common functionality for your team, you might want a repo with common includes like ./deploy.mk, ./lint.mk and so on. The include
directive supports directories as well, so you can structure these repos however you like.
include github.com/apex/make/deploy
include github.com/apex/make/lint
include github.com/apex/make/test
include github.com/apex/make/ci
Alternatively you might want one include per environment such as Node or Golang, making it easy to keep the team up-to-date.
include github.com/apex/make/node
include github.com/apex/make/golang
If you’re worried about arbitrary code execution, then simply fork a project and retain full control.
I’ve been wanting this for years but never actually got around to it! If you use Make check out the project at https://github.com/tj/mmake, and if you don’t, maybe now you’ll consider it :).