Often I find myself using third-party software like Caffeine or Amphetamine to
keep my Mac awake while running some specific commands. Sometimes it is because
I am running backups. Sometimes it is because I am compiling something.
I found out that macOS comes pre-installed with caffeinete
command… this
post is about how to integrate it in your Makefile so that running any command
there will prevent your Mac from sleeping!
The command: caffeinate
This command comes pre-installed in any mac ๐คฏ This makes my life way easier because I would not have to brew anything. This is how I am going to use it:
caffeinate -i ${COMMAND}
This will prevent the system from sleeping while the ${COMMAND}
runs.
I prefer to allow the display to sleep so that I can save some energy.
I am using the -i
flag to prevent the system from idle sleeping, while I could
also use -d
to prevent the display from sleeping. You can get more options
from a quick check in the manual (man caffeinate
).

Using it with Make
When writing a Makefile, I usually writhe commands directly. Like so:
%.out:
command $*
other-command $*
What we could do to prevent sleep or hibernation is to use caffeinate
before
every command, like so:
%.out:
caffeinate -i command $*
caffeinate -i other-command $*
But this might not be good-looking… and the senior gods of the
DRY religion might
cause your next live demo to fail! To make it better, I decided to use SHELL
variable so that every command will be passed to caffeinate
and bash
.
It will look something like this:
SHELL := caffeinate -i bash
%.out:
command $*
other-command $*
Sadly, this Makefile will not be portable, as caffeinate is available on macOS but not necessarily everywhere. So here is a simple condition to check if the binary is available and then overwrite the default shell used by Make:
# Prevent the system from idle sleeping, only on macOS
ifeq ($(shell uname -s),Darwin)
SHELL := caffeinate -i bash
endif
%.out:
command $*
other-command $*
There is a catch, though: caffeinate
on macOS works differently than the
package available here,
and that might cause issues as the flags are different. ๐ค
Therefore, instead of checking if caffeinate
command is available like this:
ifneq (,$(shell which caffeinate))
I have decided to check if the kernel/OS is Darwin/macOS. There is space for improvements here to support different GNU/Linux distros.
I have implemented this in my Ansible Playbooks, as I was always finding myself struggling with having to restart commands just because I forgot to prevent my Mac from sleeping. Now I got it fixed with just three lines of code! ๐ฅฐ