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
That brings me to a few principles that I find useful to keep in mind when creating build systems:
- 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.
- 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.
- 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.