Saturday, January 16, 2010


A co-worker of mine seems to subscribe to some mailing list where he hears about every framework and tool that ever comes into existence. And he seems to bring up each one as a potentially neat and useful addition to our tool belt at work. I tease him about it, but he is good at finding interesting things.

About one-third of his suggestions strike me as worth investigation. About one-third of those make it past a quick docs read and into my "we should incorporate this" mental bucket.

buildr is the most recent tool to run this gauntlet and end up in our source tree. buildr is a build tool that runs on top of rake, Ruby's equivalent of make, but with a Java app mindset. The mentality behind buildr seems to be, "Just because we're building Java packages doesn't mean we need to have a tool written in Java with some clunky XML config system. Maybe a scripting language would be a better choice. And, since Java build tools aren't a new frontier, let's solve the problems that are commonplace in them while we're at it."

Java's standard build tools have notable flaws. The original authors of ant decided that ant should not be a programming language. The problem is that you often want some flow-of-control/variable setting for specialized tasks in your build, and you certainly want some ability to modularize. Because ant doesn't give you lots of ways to do these things (though there are add-ons that fill this gap), you end up with verbose XML files with an annoying amount of repetition. (If you're in this boat, you might want to check out the "Refactoring Ant Build Files" essay in The ThoughtWorks Anthology.)

Maven tried to fix some of ant's problems with a convention-over-configuration mindset: Set up a directory structure in a standard way, and maven's plugins will do the right thing with a minimum of configuration. Deploying a normal war required about three lines of XML. Maven also introduced a notion of dependencies and repositories. In an ant system, you find a library you need, download its jar into your source tree, and check it in. In the Maven universe, you just put an entry in your build file, and Maven goes and fetches the jar from a network-based repository.

But should you need to stray from the convention, Maven gets in your way. Want to use the ant technique of downloading a library for some reason (like, for instance, it's an Oracle driver that can't be published from Maven repositories because of licensing)? You can set up an internal repository, but it's a fair amount of work for a developer on a small team with a lot of other things to do. You can customize Maven (and ant, for that matter) with plugins written in Java, but that always seems clunky.

Buildr tries to solve these problems. It does all the dependency stuff that Maven does, but it also allows you to construct an artifact object (the term for a built resource) around an arbitrary file. Setting up buildr at work, I faced the problem that the Oracle drivers I need aren't in the global Maven repository anymore. So I downloaded the jar, stuck it in a lib directory, and just created an artifact reference to that file. (One caveat: buildr doesn't yet do the "transitive dependency tracking" that Maven does. In Maven, if you need a library, the system will fetch it and all the libraries that that library depends on. buildr requires you to list every single dependency.

Buildr also supports hierarchical/environment-specific properties as a feature. You often need to have properties files that contain different values for different environments (database connection URLs, for instance), and you usually have to roll your own solution. buildr acknowledges this common need and just addresses it.

And if you need to do something specialized, you can write Ruby code inline. No building a Java library that conforms to some API and then configuring the build tool to use it.

I've got local builds working in buildr, but I need to convert our automated build systems to use it. Once those are in place, I plan to move forward with buildr as our sole build tool.

1 comment:

  1. Good article, buildr is nice.

    But I was under the impression that buildr did indeed handle transitive dependencies (with the transitive directive):