Been working this week on Savant 2.0. My first thought when I started writing Savant 2.0 was to write a complete replacement for both Maven and Ant that used Groovy and allowed for both a plugin model as well as a simple build script approach. This was too much to bite off when you consider all of the other changes to the dependency management part of Savant we made for 2.0.
For JCatapult we created a set of Ant build scripts that could be plugged into any build file and reused. It looks like this:
<project name="foo"> <import file="${jcatapult.home}/ant/plugins/java/1.0/compile.xml"/> ... </project>
This model meant that the build.xml file had nothing but import statements in it. It made life much simpler when working with numerous projects that were virtually the same.
The part I didn’t like was that I loved this model. I liked it so much I started using them for everything including Java.net Commons, Savant and internal Inversoft projects. This meant that I had a dependency on JCatapult, which for all intents and purposes is a webapp platform. This seemed strange.
I started thinking about moving these files over to Savant. At first I just figured I would migrate the entire set of Ant plugins from JCatapult over and be done. However, once I moved them over it meant that I would need to start pulling in plugins for a variety of projects. Some would come from Savant and others might come from JCatapult or elsewhere. This was due to the fact that some of the JCatapult plugins were very specific to JCatapult projects. I could force developers to download each plugin they needed from various places, install them in a specific directory and then update their build files before they could build any projects. It all started to look very clunky.
Then I remembered (duh!) that Savant is a dependency management tool and it can find, version and download ANYTHING. Why not apply this pattern to Ant build files in the form of plugins?
So, I did just that!
It works great. The way it works is that I wrote a simple Java class that figures everything out and then generates an ant build file. The full process looks like this:
- New script called svnt invokes a Savant class
- This new class parses the project.xml file, which defines the plugins the project will be using
- It downloads any missing plugins to the Savant local cache
- Since the plugins are JAR files, it explodes the JAR file to ~/.savant/plugins under a specific directory just for that plugin
- This class then generates a temporary build.xml file that imports all of the plugins the project needs
- It outputs the location of this temporary build.xml file
- The svnt script executes Ant passing it the location of this build file (i.e. ant -f /tmp/tmpbuild.xml)
And that’s it. Nothing fancy, just a little sugar on top of Ant to provide downloading of plugins and build files automatically.
The last part of this exercise is to write a bunch of plugins. Since these are just Ant build scripts and we’ve all created hundreds of those so it should be a simple matter of tweaking them ever so slightly to work when imported.
My new projects don’t have a build.xml file (but if they do it is imported to add additional targets or override targets from the plugins) and just contain the Savant project.xml file. This file now defines plugins and it looks like this:
<project name="foo" group="inversoft.org" version="1.0"> <plugin group="plugins.savant.inversoft.org" name="clean" version="1.0"/> <plugin group="plugins.savant.inversoft.org" name="java" version="1.0"/> <plugin group="plugins.savant.inversoft.org" name="junit" version="1.0"/> <plugin group="plugins.savant.inversoft.org" name="release-svn" version="1.0"/> ... </project>
That’s it. If anyone is interested in trying it out, I should have a release available in the next few days along with some documentation for the 5-10 plugins I will have ready. If you want to try and build all this by hand right now, you’ll need to install JCatapult since Savant uses that until it can be self building.