The Blog

Sep 8, 2007

Build Tools 

by Maxim Porges @ 9:24 PM | Link | Feedback (0)

We've been messing around for a while at work with various options for automated build tools. Naturally, our journey started with Ant, but in recent days we've been veering down the path of more complete solutions.

The challenges we've been facing are as follows.

1) Dependency resolution is a pain in the ass. We're trying to standardize the libraries our Java apps rely upon to a certain extent but allow exceptions where necessary, which has resulted in variation in the build process for each project (precisely what we want to avoid).

2) Our Ant scripts for many of our projects basically all look the same. This breeds repetition in the builds, which could be a real problem if we change our build process significantly or decide to add new requirements later on.

3) Ant is painful to script in when you need to step outside the box. You can certainly do it using a variety of tools and extensions; I had the most luck incorporating BeanScripting in to Ant to automate SVN tasks, and was able to use some module extensions (from Antelope if I recall) to get something approaching reusable functions. However, you end up with blended XML tags and script code, and it's certainly much clunkier than pure scripting.

4) We need to be able to customize our build process for varying environments; specifically development, unit testing, quality assurance testing, and production. For each environment, we need to be able to specify different settings, and in some cases get around inconsistencies in our hardware, app server, or OS environments (which while very undesirable are currently unavoidable).

5) Initially, we're just trying to tackle 100% build automation and deployment, but over the long term we want to add a lot of bells and whistles, such as automatically generating and deploying a common documentation repository with JavaDocs and other useful artifacts. Whatever tool we choose needs to be able to support this capability.

6) We have several technology choices to support at CFI: Java, ColdFusion, and Flex. We will likely be adding more in the future, and although there is little infrastructure to support it today, it would be nice for us to automate the build process for our legacy Oracle Forms and PL/SQL apps as well (so long as we are maintaining them).

To meet these challenges, LeGros kicked off a little project to evaluate several tools that would potentially fit in to our environment: Buildr, Ivy, Raven, and Maven 2. For each tool, a developer was assigned to review the functionality and build a small sample project as a proof of concept.

We'll start with Ivy, since it's the simplest of the tools that we evaluated. Ivy essentially adds dependency resolution capabilities to Ant. It can use a variety of dependency resolution methods, including Maven repositories (something we found all the tools were able to hook in to - pretty much the only common thread).

Ivy is attractive because we can plug it in to the existing Ant scripts that we have, so it carries the shortest learning curve for our development teams. Unfortunately, it doesn't really address the other challenges that we have to face in any way; we'd have to continue to script solutions for these problems.

Raven is a build tool for Java based upon Rake, which I've never used but I understand is very popular for Ruby/Rails projects. Raven essentially brings Rake-style builds to Java projects, and resolves dependencies through a Gem repository, which (again) I'm unfamiliar with but seems akin to the Maven repositories.

Raven looks promising because you script it with Rake tasks and Ruby, and Ruby is clearly a fantastic and terse scripting language. Unfortunately, when Dan evaluated Raven, he felt like there wasn't a lot of support on the project when compared to the others (Ivy has been adopted by Apache and both Buildr and Maven have active communities supporting them). We don't really want a tool that isn't growing and changing with fervour, so I'm doubtful we'll end up adopting Raven as a result.

Buildr is essentially a Ruby implementation of Maven, which makes use of a Ruby-based DSL for builds instead of Maven's verbose XML syntax. Buildr was started by a team that found Maven incredibly frustrating to use for builds, which bodes well; in my experience, projects born of frustration tend to be very practical and a pleasure to use (Spring and Mule come to mind).

That being said, something I have often found discouraging in the development community is the ease with which people dismiss projects and technologies in favor of fads. Java and its community have taken a real beating from people in recent years, and while much of the criticism is well deserved, a lot of it is delivered with logic applied painfully out of context. I've learned a lot of good things from the lighter, more agile approaches and technologies favored today, but I've also seen many of these ideas work beautifully on a project supporting a single small application but fail horribly or scale inappropriately in a corporate setting that is much larger and more complicated. I'm hoping the team behind Buildr hasn't fallen foul to this dismissive attitude, and that the tool fits well and scales appropriately across any scenario.

Buildr's benefits of Ruby scriptability and a terse build file format look appealing indeed, plus the fact that Buildr plugs in to Maven-style repositories. The ability to use a Maven-style repository would allow us to use Buildr and Ivy together, providing a clean crossover from (or backwards compatibility for) our existing Ant builds and solving the dependency problem across the board. Maven's the only build tool I've been able to play so far, but Buildr is the next one I want to dig in to for building a fully-fleshed proof of concept.

Maven 2
The current release of Maven is claimed to be a massive improvement over the former version, and seems to be the de facto standard for building projects created by the Apache group. Maven sprouted after an Apache developer tired of scripting huge builds in Ant, so it has that "born of frustration" component that I tend to find promising, as well as being something of a natural evolution from Ant. Maven is based on an XML build syntax and a convention-over-configuration approach, and has some pretty cool features such as project inheritance and modularization. There's a rich library of plug ins for Maven, and the repositories that most of the tools mentioned so far support are based on an original Maven standard.

On the downside, Maven has a reputation for not working as expected and/or becoming painful to work with when you step outside of the convention box. As a result, we had a bad taste in our mouths for Maven, felt that it would have a steeper learning curve for our developers, and would have a high level of impact on our projects, since they would have to be completely converted to Maven's conventions in order to get the benefits of the convention-over-config approach.

Well, that's it for the round up on our build tools. I've decided to play with Maven and Buildr. Raven seems ruled out based upon the relative lack of maturity and community support, and Ivy basically does what it says on the box and doesn't require further investigation in my mind.

I'm going to add some separate blog posts for Maven and Buildr, documenting my experiences with them and overall impressions. The build process I'm using as the POC has to be able to do the following:

1) Build a complete project as follows: checkout from SVN, resolve dependencies, compile, test, package artifacts, and deploy final artifacts to a repository. Build options, compilation/test options, and final repository location must be configurable for our multiple target environments.

2) Bootstrap a project for development: checkout from SVN, create an Eclipse project with all appropriate builders and configurations in place, set up library dependencies, and import the project in to the developer's workspace ready for action.

3) Generate documentation: at the bare minimum, create JavaDoc files and publish them to an appropriate destination (such as a development staging area for code under development, or a production instance for live code).

4) Support extension and scriptability. One item that immediately comes to mind is the ability to execute database scripts at deployment time, but I'm sure there will be other cases in the future. We need something that is flexible to our current and future needs.

I hope you will come along with me for the ride and post your questions and thoughts. We've got an ongoing thread of sessions at Adogo right now for configuration management and build tools, kicked off at this month's session with LeGros's excellent talk on Subversion, so if you're in the Orlando area I recommend you join us if this is a topic in which you have an interest.