Random thoughts on build systems

5

I’ve logged a lot of time in the last few weeks hacking build stuff. I’ve written or rewritten build systems in the past at almost every job I’ve ever had. My first experiences were building C++ products using Make (and variants). Later, I wrote build systems for Java in the dark pre-Ant days using a combination of custom Java code, shell scripts, and Perl. And since then I’ve written a number of build systems primarily using Ant and CruiseControl.

In general, I find Ant (and extensions) are capable of doing about 95% of what I need and it’s really easy to write custom tasks for the last 5%. If you’re doing a lot of Ant, you can probably make use of something in either ant-contrib or ant4eclipse. From ant-contrib I’ve mostly used the flow control constructs like <if> and <foreach>. I realize these flout traditional Ant style, but in my experience they make build files easier to understand and maintain, and those are qualities that I hold in very high regard for build systems. ant4eclipse provides a set of helpful tasks that let you create build systems dependent on Eclipse configuration files.

That brings me to a few principles that I find useful to keep in mind when creating build systems:

  1. Readable and maintainable – Build systems are rarely maintained by one person over the lifetime. It is much more common for them to be maintained by a succession of people or maintained part-time by a team of people. For this reason, it is crucial that build systems be as well documented and easy to understand as possible.
  2. Repeatable on any machine – It makes things much much easier if the build is not tied to a particular build machine. This helps for developing and testing the build on a dev machine, moving the build between machines, and avoiding specialized per-machine logic.
  3. Mimics dev environment – It’s really important that the build you run on your build box nightly matches the way developers build and run their tests locally to as high a degree as possible. Otherwise, you will waste a lot of time trying to figure why something fails in the nightly build but works locally or vice-versa. In practice, this can be really difficult, but it’s worth the effort.

Something I think about a lot is whether all this customized build logic is fixable in the general case (whether it can be standardized and transferred across systems). I think Maven is really interesting and tries to provide a standard framework for “normal” builds. However, I’m not sure that there is such a thing as a “normal” build.

I’d say the idea of formalizing dependency management into your build via something like Maven or Ivy is a problem that needs to be and can be solved. And for that matter, the parts of a build that compile source, run tests, and create jars is usually within a fairly narrow range. But my experience has been that that stuff is usually only a small percentage of a typical build system, which will cover copying builds around, creating installers, updating source control systems, sending emails, and a dizzying array of other customized pieces.

I can’t say I have any answers to any of this, just brain dumping while it’s on my mind. I’ve certainly heard a lot of arguments both for and against Maven. I haven’t used it personally, so I’m withholding judgment until I get some first-hand experience. I’d love to hear what people have experienced with some of the commercial build systems and how they compare to something like Ant or Maven.

Comments

5 Responses to “Random thoughts on build systems”
  1. I’ve had a decent amount of experience with Maven. When I started my last job, we were using a huge, unwieldly Ant build. I was charged with moving this to Maven 1, and later to Maven 2. At my current job, we’re using Ant.

    The thing to keep in mind about Maven, is that, like Rails, it’s opinionated. If you following their conventions, life is bliss. Otherwise, you’ll be in for some hurt.

    When you do follow the conventions, you get a lot of benefits for free. For example, starting to use Clover, PMD, Checkstyle, and similar, requires literally no effort. You just tell Maven to run the appropriate plugin, and it takes care of the rest.

    The trouble starts when you get to the edges of what plugins offer. The documentation for plugin development always seemed very scant (although, I found this to be true for most of Maven). Existing plugins were usually recommended as examples, but that doesn’t help when there aren’t good examples for what you’re trying to do.

    In our case, we were using BEA’s JDO implementation (at the time Kodo, which was owned by Solarmetric), and it needs to do it’s JDO enhancement after building. There wasn’t a plugin for it that did everything we needed, so we looked into writing our own. To make a long story short, we gave up and ended up using the ant plugin to invoke Kodo’s ant tasks.

    All in all, it was a love-hate relationship for me with Maven.

  2. Anonymous says:

    Maybe im wrong but more tha 600 open issues on maven 2.0.7 is enough to stop using the tool.

  3. LSM says:

    Some good points, the kind of things you tend to think of and either implement or keep in mind to do later. Only thing with build scripts are they are boring.

  4. Muanis says:

    Alex, I totally agree with you.

    We have a lot of ant scripts in our company. Most of them are derived from a initial example that “left in the field of war” grown its own “bad” habits.

    Keeping in mind that the best build tool is the one that solves your problem with less effort. I would say that, if you´re gona create a new project, you should go for something like maven or buildr. Migrate a huge project from using ant to “any” other can be a nightmare.

    A good point is that usually you have a small number of people “able” to handle buildfiles. Wich is good in a sense, afterwards you don´t want any freshman poking around the dependencies of your application.

    I like the dependency management provided by maven (actually just used maven 1). And in my dreams I want to migrate the dependency managemente I´ve built on top of ant scripts to a more organized way (Ivy is one of the options).

    But … one point that I´ve never saw in any of these, is that our dependencies, include configuration data, wich is specific of each environment (dev, qa etc). I would have something like mydependency.jar:1.2.3:qa like having a profile for a version.

  5. Michael Böckling says:

    You can do that with maven, its called classifiers. The file would be named mydependency-qa-123.jar, for example.

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!