Friday, September 14, 2007

Impala's non-Maven approach to simpler builds

One of the goals of Impala is to have a pure work out-the-box feeling. If you download the distribution, you should be able to set up a new project with just one or two commands. Once you've done this, the project structure should be ready for you. The build infrastructure should be just there. As long as you obey the project structure conventions, then you should be able to plug in an existing build system into your new project.

All of this is behind the ideas that drive Maven. Maven defines a standardised folder locations, and an existing build infrastructure which you can just plug in and use. All of these ideas are great, but I don't want the project to depend on Maven. I'm still trying to decide whether I should make the project structure conventions conform to those of Maven. The advantage is that Maven users would be able to simply Mavenize their project by adding a POM xml. The disadvantage is personal - I don't particularly like the Maven project structure conventions. I wouldn't have chosen them for myself.

Right now I'm pretty close to having a pure out-of-the-box ANT based build system ready for Impala. It's taken quite a lot of time, but it's starting to feel much more right. Basically, the build will be enabled using the following combination:
  • a build.xml in the project root directory. The build.xml needs to have a property called impala.home, which defines where the Impala install files have been dumped to on the file system
  • a set of other project-specific properties which need to be specified, either within the build.xml itself a properties file
  • a set of imports of build scripts sitting in the impala.home folder
Here's an example:

<?xml version="1.0"?>
<project name="Build" basedir=".">

<property name = "workspace.root" location = "..">
<property name = "impala.home" location = "${workspace.root}/../impala">
<property file = "build.properties">
<import file = "${impala.home}/project-build.xml">
<import file = "${impala.home}/download-build.xml">

</project>
Note that the clean, compile, jar and test targets typical in a build system are found in project-build.xml. This file in turn relies on your project structure conventions to find the resources it needs. Similarly, adding download-build.xml adds support for obtaining dependencies, for example from a Maven ibiblio repository. You can make this build file the master build file for a multi-project build, simply by adding an import to shared-build.xml and adding the project.list property, as shown in this example:
<?xml version="1.0"?>
<project name="Build" basedir=".">

<property name = "workspace.root" location = ".."/>
<property name = "impala.home" location = "${workspace.root}/../impala"/>

<echo>Project using workspace.root: ${workspace.root}</echo>
<echo>Project using impala home: ${impala.home}</echo>

<property file = "build.properties"/>
<import file = "${impala.home}/project-build.xml"/>
<import file = "${impala.home}/shared-build.xml"/>
<import file = "${impala.home}/download-build.xml"/>
<import file = "${impala.home}/repository-build.xml"/>

<target name = "get" depends = "shared:get"/>
<target name = "fetch" depends = "repository:fetch-impala"/>
<target name = "clean" depends = "shared:clean"/>
<target name = "dist" depends = "shared:all-no-test"/>
<target name = "test" depends = "shared:test"/>

</project>
with the extra property in build.properties:
project.list=wineorder,wineorder-hibernate,\
wineorder-dao,wineorder-merchant,wineorder-web
I'm looking forward to getting all of this work done, so I can get back to what Impala is really supposed to be doing, which is supporting dynamic Spring modules. But all of this functionality is terribly important for making the whole experience as painless as possible for end users.

No comments: