Makefiles to Rule Them All

In my last blogpost you might have already stumbled over me using a Makefile to simplify a project task. My enthusiasm for Makefiles goes a bit further and I add one to most of my projects by now. Here is why I do this and how they make my everyday developer life a bit easier.

None of my projects is written in C or C++ which rely on a Makefile for compiling them. Instead my projects are written in JavaScript (Node), Ruby and PHP. I use the make command as a wrapper for the individual tools coming with each ecosystem to create a common interface. This way I can just run make test no matter whether the tests are in JavaScript and use Mocha or use PHPUnit.

Besides the different set of tools belonging to a platform (e.g. Node's npm, PHP's Composer and Ruby's Bundler) there are a few more difference between projects that I created a shortcut for: To run a project locally it might be anything between npm run, a Docker container or a Vagrantbox. And on the plain level of a project's structure there is also a wide variance: Everything might be in the root directory, or split in a src/ and docker/ directory. Every project is its own special snowflake in this regard.

After a short trial with shell scripts to do repetitive tasks always from the project root I quickly switched to use make instead. It's widely available and make it easy to handle different commands. So I started to develop my strategy for Makefiles. It's schema applies to most of my web-based projects perfectly:

  • make setup -- Does everything which might be necessary on the first setup like installing the dependencies, like run npm install for a node-project.
  • make run -- This will mostly default to docker-compose up. Or to bundle exec jekyll serve --drafts for this blog.
  • make test -- You might have guessed it: This one executes the unit tests of the project.

Of course it doesn't stop there. There are often a bunch more commands which might for example trigger an existing build system like ant. Or just as an alias for the npm scripts. Nonetheless it's a great shortcut saving me quite some time when switching between projects.

A small example for a PHP project, which uses Composer and comes with a Docker-Compose setup. The tests are executed within the Docker container.

.PHONY: setup
setup:
	@cd src/ && \
	composer install

.PHONY: test
test:
	docker-compose run web /bin/bash -c 'composer test' && exit

.PHONY: run
run:
	docker-compose up -d

So if you also happen to often switch between diverse projects, maybe you also want to give Makefiles a try.