Laziness with Make
I have lots of shell aliases/functions for repetitive tasks. Copying files to and from servers, removing editor backup files, connecting to specific databases, the list goes on.
Sometimes however the thing I want to do is directory specific. A
good example of this is when I’m developing scripts. Typically, I edit
in the comfort of my desktop, and copy scripts to the server for
testing. As I’m often working on multiple files, I use rsync
to keep
the remote directory in sync.
# Edit
rsync -av . example.com:some/directory/path
# Test
This keeps the local and remote directories in sync, uploading only the files that have changed. There are other work-flows I could use, for example, my editor supports remote editing with SSH, but rsync works for me. I’m lazy, and don’t want to have to type out the rsync command or even find it in my history. Normally, I’d reach for an alias, but each project has a different target host and/or directory.
So instead, I reach for
Make. The
short version is that given a Makefile in the current directory
running make
will cause commands in that file to be run. Make is
about as old-school as it gets, if you have a compiler installed you
have Make, this setup works just about anywhere.
The Make syntax is Turing complete, but for this simple example we just need the name of a target and the command we want to run:
.PHONY: sync
sync:
rsync -av . example.com:some/directory/path
Since we have only one rule, the name doesn’t matter. The first rule
in a Makefile the default, so that’s what’s going to run when we type
make
.
One slight bit of complexity. Make’s true job in life is to
create/update the target, which is expected to be a file. It checks if
the target is older than it’s dependencies (if any) and runs the
command only if the target needs updating. .PHONY sync
tells Make
that the target isn’t a real file. We need this so Make will run the
command if a file with the name of our rule happens to exist in
current directory.
If you are a Ruby developer, you also have
Rake and can use it instead by
creating a Rakefile
:
task :default do
sh 'rsync -av . example.com:some/directory/path
end
Unlike Make, Rake requires you to have an explicit default task, which
you can do by calling it default or by creating an alias in the form
of task default: :sync
. Also unlike Make, Rake doesn’t treat targets
as files in needs to create, unless you tell it to (and that’s another
show).
There is no advantage to using Rake over Make, go with what you are comfortable with.
Of course in keeping with my lazy streak, I have a function to the create the Makefile.
function setup-rsync() {
if [ ! -f Makefile ]; then
printf ".PHONY: sync\nsync:\n\trsync -av . $@\n" > Makefile
fi
}
Now I can just run setup-rsync example.com:some/directory/path
once
and make
from then on. Laziness for the win!
Comments