Monday, February 20, 2006

Bootstrapping Maven dependencies into Ant

One thing about builds I detest: packing the universe into the source tree. Maven and Ivy are two good solutions for this problem, keeping your external dependencies out of your source control system. And they both work with Ant.

But how to get the ball rolling?

Helpfully, Ant has the get task for fetching files from the Internet. Thus I can fetch Ivy or the Maven-Ant bindings, plug them into build.xml, and pull down my other dependencies all without checking in anything outside of my project.

Here's how:

  1     <property name="target.dir" location="target"/>
  2     <property name="maven-artifact-ant.bootstrap.jar"
  3               location="${target.dir}/maven.artifact-ant-2.0.2-dep.jar"/>
  4 
  5     <target name="-check-get-maven-artifact-ant">
  6         <available property="-get-maven-artifact-ant-done"
  7                    file="${maven-artifact-ant.bootstrap.jar}"/>
  8     </target>
  9 
 10     <target name="-get-maven-artifact-ant"
 11             depends="-check-get-maven-artifact-ant"
 12             unless="-get-maven-artifact-ant-done">
 13         <mkdir dir="${target.dir}"/>
 14         <get src="http://www.apache.org/dist/maven/binaries/maven-artifact-ant-2.0.2-dep.jar"
 15              dest="${maven-artifact-ant.bootstrap.jar}"/>
 16     </target>
 17 
 18     <target name="-maven-artifact-ant" depends="-get-maven-artifact-ant">
 19         <typedef resource="org/apache/maven/artifact/ant/antlib.xml"
 20                  uri="urn:maven-artifact-ant">
 21             <classpath>
 22                 <pathelement location="${maven-artifact-ant.bootstrap.jar}"/>
 23             </classpath>
 24         </typedef>
 25     </target>
 26 
 27     <target name="init" depends="-maven-artifact-ant">
 28         <tstamp/>
 29         <!-- All the other init tasks: buildnumber, mkdir, et al -->
 30     </target>

In essence the steps are:

  1. Check if there is already a downloaded jar (-check-get-maven-artifact-ant).
  2. If not, fetch one from a well-known location (-get-maven-artifact-ant).
  3. Load the bindings from the jar into Ant (-maven-artifact-ant).

Now build.xml is ready to proceed with Maven (or Ivy) for fetching dependencies and deploying them.

3 comments:

Anonymous said...

What's wrong with doing it like this?

http://maven.apache.org/ant-tasks.html

Seems neater to me.

You can also have multiple repositories and therefore use it for resovling internal dependancies by running a local webserver for those. In addition to that you can run a local server for binaries that aren't so easy to download. Such as those from Sun that require signing a EULA.

Plus it sets up your classpath and/or filesets for you.

Moreover it allows declarative definition of versions.

Anonymous said...

Sorry, just re-read your post I missed the point. You were using it to bootstrap maven which is a great idea.

Please feel free to delete my ramblings - how embarassing.

Brian Oxley said...

No big deal; it happens to all of us. I'm just glad you aren't cursing profanely like some posts, or trying to sell me on an amazing, no-way-to-lose business proposition.

Put another way, my post could have been more clearly written in the first place. Your mistake tells me the problem with with the writing even if the content is correct.