As a software developer, I care deeply about my build tools. I strive to provide easy-to-use and understand build scripts with my projects, so that other folks can rebuild a project I'm working on, as simply as possible. Often one of those other folks is me, coming back to a project after being away for it for months, or years.
I cut my teeth on make
. So awesome, for it's time. Even today, all kinds
of wonderful things about it. But there are problems. Biggest is ensuring
Makefile
compatibility across all the versions of make
you might encounter.
I've used make
on OS/2, Windows, AIX, Linux, Mac, and other Unix-y platforms.
The old version of Windows nmake
was very squirrelly to deal with, and if
you had to build a Makefile
that could run on Windows AND anywhere else,
well best of luck, mate! make
is also a bit perl-ish with all the crazy
syntax-y things you can do. It's driven me to near-insanity at times.
I was also a big user of Ant
. I don't do Java anymore, and would prefer
to not do XML either, but I do still
build weinre with Ant.
Since I'm primarily doing node.js stuff these days, it makes a lot of sense
to use a build tool implemented on node.js; I've already got the runtime
for that installed, guarantee. In the past, I've used jake
with the
Apache Cordova project, and have flirted with the newest build darlings of the
node.js world, grunt
and gulp
.
I tend towards simpler tools, and so am happier at the jake
level of simple-ness
comared to the whole new way of thinking required to use grunt
or gulp
, which
also have their own sub-ecosystem of plugins to gaze upon.
Of course, there are never enough build tools out there, so I've also built some
myself: jbuild
. I've been using jbuild
for projects since I built it, and
have been quite happy with it. But, it's my own tool, I don't really want to
own a tool like this. The interesing thing about jbuild
was the
additional base level functionality it provided to the actual code you'd
write in your build scripts, and not the way tasks were defined and what not.
As a little experiment, I've pulled that functionality out of jbuild
and
packaged up as something you can use easily with cake
. cake
is one
the simplest tools out there, in terms of what it provides, and let's me
write in CoffeeScript, which is closer to the "shell scripting" experience
with make (which is awesome) compared to most other build tools.
Those extensions are in the cakex
package available via npm
.
why cakex
shelljs
function built in as globals. So I can do things likemkdir "-p", "tmp" rm "-rf", "tmp"
(that's CoffeeScript) right in my
Cakefile
. Compare to how you'd do that in Ant. heh.scripts in
node_modules/.bin
added as global functions that invoke those scripts. Hat tip,npm run
. So I can do things likeopts = """ --outfile tmp/#{oBase} --standalone ragents --entry lib/ragents.js --debug """ opts = opts.trim().split(/\s+/).join(" ") log "running browserify ..." browserify opts
functions acting as watchers, and server recyclers. I always fashion build scripts to that they have a
watch
task, which does a build, runs tests, restarts the server that's implemented in the project, etc. So that when I save a file in my text editor, the build/test/server restart happens all the time. These are hard little things to get right; I know, I've been trying for years to get them right. Here's an example usage:taskWatch = -> watchIter() # run watchIter when starting watch files: sourceFiles # watch sourceFiles for changes run: watchIter # run watchIter on changes watchIter = -> taskBuild() # run the build taskServe() # run the server taskServe = -> log "restarting server at #{new Date()}" # starts / restarts the server, whichever is needed daemon.start "test server", "node", ["lib/server"]
The cakex
npm page - https://www.npmjs.com/package/cakex - includes a
complete script that is the kind of thing I have in all my projects, so you
can take in the complete experience. I love it.
Coupla last things:
yup, globals freaking everywhere. It's awesome.
I assume this would be useful with other node.js-based build tools, but wouldn't surprise me if the "globals everywhere" strategy causes problems with other tools.
I'm using
gaze
to watch files, but it appears to have a bug where single file patterns end up matching too many things; hence having to do extra checks when you're watching a single file.I've wrestled with the demon that are the
daemon
functions incakex
for a long time. Never completely happy with any story there, but it's usually possible to add enough hacks to keep things limping. Wouldn't be surprised if I have to re-architect the innards there, again, but hopefully the API can remain the same.Please also check the section in the README titled "integration with
npm start
", for what I believe to be a best practice of including all your build tools as dependencies in your package, instead of relying on globally installed tools. For node.js build tools anyway.