Use Makefile as the task runner for arbitrary projects

Pass arguments

# in Makefile

.PHONY: something
something:
ifeq ($(var),foo)
    @echo $(var) "bar"
else
    @echo "others"
endif
$ make something var=foo
foo bar

$ make something
others

ref:
https://stackoverflow.com/questions/2214575/passing-arguments-to-make-run

Detect OS

# in Makefile

ifeq ($(shell uname),Darwin)
    UPDATE_COMMAND = brew update
else
    UPDATE_COMMAND = apt-get update
endif

Check whether a file or directory exists

# in Makefile

ifneq ($(wildcard /usr/local/HAL-9000/bin/hal),)
    UP_COMMAND = /usr/local/HAL-9000/bin/hal up
else
    UP_COMMAND = docker-compose -f docker-compose.yml -f docker-compose.linux.yml up
endif

up:
    $(UP_COMMAND)

install:
    pip install -r requirements_dev.txt

ref:
http://stackoverflow.com/questions/20763629/test-whether-a-directory-exists-inside-a-makefile

What does .PHONY mean?

Let's assume you have install target, which is a very common in makefiles. If you do not use .PHONY, and a file named install exists in the same directory as the Makefile, then make install will do nothing.

ref:
http://stackoverflow.com/questions/2145590/what-is-the-purpose-of-phony-in-a-makefile

Call another target in the same Makefile

Say that coverage depends on clean.

.PHONY: clean
clean:
     find . -regex "\(.*__pycache__.*\|*.py[co]\)" -delete

.PHONY: coverage
coverage: clean
     docker exec -i -t streetvoice_django_1 python -m coverage run manage.py test --failfast
     docker exec -i -t streetvoice_django_1 python -m coverage html -i

ref:
http://stackoverflow.com/questions/13337727/how-do-i-make-a-target-in-a-makefile-invoke-another-target-in-the-makefile