views:

286

answers:

4

Is there a well-established way to share Ant targets between projects? I have a solution currently, but it's a bit inelegant. Here's what I'm doing so far.

I've got a file called ivy-tasks.xml hosted on a server on our network. This file contains, among other targets, boilerplate tasks for managing project dependencies with Ivy. For example:

<project name="ant-ivy-tasks" default="init-ivy"
         xmlns:ivy="antlib:org.apache.ivy.ant">
  ...
  <target name="ivy-download" unless="skip.ivy.download">
    <mkdir dir="${ivy.jar.dir}"/>
    <echo message="Installing ivy..."/>
    <get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
         dest="${ivy.jar.file}" usetimestamp="true"/>
  </target>

  <target name="ivy-init" depends="ivy-download"
          description="-> Defines ivy tasks and loads global settings">
    <path id="ivy.lib.path">
      <fileset dir="${ivy.jar.dir}" includes="*.jar"/>
    </path>
    <taskdef resource="org/apache/ivy/ant/antlib.xml"
             uri="antlib:org.apache.ivy.ant"
             classpathref="ivy.lib.path"/>
    <ivy:settings url="http://myserver/ivy/settings/ivysettings-user.xml"/&gt;
  </target>
  ...
</project>

The reason this file is hosted is because I don't want to:

  • Check the file into every project that needs it - this will result in duplication, making maintaining the targets harder.
  • Have my build.xml depend on checking out a project from source control - this will make the build have more XML at the top-level just to access the file.

What I do with this file in my projects' build.xmls is along the lines of:

<property name="download.dir" location="download"/>
<mkdir dir="${download.dir}"/>
<echo message="Downloading import files to ${download.dir}"/>

<get src="http://myserver/ivy/ivy-tasks.xml" dest="${download.dir}/ivy-tasks.xml" usetimestamp="true"/>
<import file="${download.dir}/ivy-tasks.xml"/>

The "dirty" part about this is that I have to do the above steps outside of a target, because the import task must be at the top-level. Plus, I still have to include this XML in all of the build.xml files that need it (i.e. there's still some amount of duplication).

On top of that, there might be additional situations where I might have common (non-Ivy) tasks that I'd like imported. If I were to provide these tasks using Ivy's dependency management I'd still have problems, since by the time I'd have resolved the dependencies I would have to be inside of a target in my build.xml, and unable to import (due to the constraint mentioned above).

Is there a better solution for what I'm trying to accomplish?

+1  A: 

After some additional searching, a possible solution would be to use SVN externals to check out specific required files that may be needed by the build.xml.

However, this would only work for users who are using Subversion as source control. It would still be nice to have a SCM-agnostic solution for users who aren't using Subversion, or another SCM that supports similar functionality.

Rob Hruska
+1  A: 

If you use Antlibs you can package them all inside a JAR file. Then simply copy this file into the ${ANT_HOME}/lib directory to use them.

Vladimir
A: 

Not really an answer, but feedback to the existing answers.

I came here to look for solutions to the same problem, we're trying to move away from SVN externals due to the fact that they really slow down status, update and checkout operations if you have a lot of projects (and personally I would like to use git-svn).

The antlibs suggestion is interesting, but if I'm not mistaken you can only define new types and macros. What we want to do is to define targets, otherwise you will still end up duplicating chunks of ant.xml

Sharebear
Yeah, that's what I gathered from the Antlib information, although I haven't had a chance to try it out yet.
Rob Hruska
agreed. I read that Ant is working on a mechanism to load the build.xml file from a jar, and that would solve most problems. If your projects are +/- standards, than your ant.xml files will be tiny tiny. For an example, take a look at http://code.google.com/p/workingonit/source/browse/trunk/linguae/build.xml . IMO it's a workaround that is quite usable.
Vladimir
A: 

What we've done is to create a project called 'bootstrap' which contains the various xml-files needed for the other projects at our office. So to set up your development environment you run build.xml in bootstrap which copies the xml-files (like your ivy-stuff, and other targets) to a known location, and then your build files include these like this:

<import file="${ant.bootstrap.dir}/ant-commons.xml" />
<import file="${ant.bootstrap.dir}/ant-commons-ear.xml" />

Our bootstrap build.xml contains this:

<target name="install">
        <fail unless="ant.bootstrap.dir" message="ant.bootstrap.dir ${missing.property.message}"/>
        <copy todir = "${ant.bootstrap.dir}">
            <fileset dir = "src/xml"/>
        </copy>
</target>
slipset