Question

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"/>
  </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?

Was it helpful?

Solution

If you are using ANT 1.8+, then you could just import the build.xml directly from the hosted location.

http://ant.apache.org/manual/Tasks/import.html

Since Ant 1.8.0 the task can also import resources from URLs or classpath resources (which are URLs, really). If you need to know whether the current build file's source has been a file or an URL you can consult the property ant.file.type.projectname (using the same example as above ant.file.type.builddocs) which either have the value "file" or "url".

<!-- importing.xml -->
<project name="importing" basedir="." default="...">
  <import file="http://myserver/ivy/ivy-tasks.xml"/>
</project>

OTHER TIPS

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.

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.

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top