Question

I am building a project using Ant and Ivy. The build.xml file depends on ant-contrib, bean scripting framework, beanshell, and commons-logging.

Ant searches for libraries in several places, including ${user.home}/.ant/lib.

Is there any way in the build.xml file to have these libraries automatically download and install in the ${user.home}/.ant/lib directory if they are not already present, perhaps using Ivy itself?

Thanks, Ralph

Was it helpful?

Solution

I happened on this question as I was reading the Ivy cachefileset documentation, which states:

Please prefer the use of retrieve + standard ant path creation, which make your build more independent from ivy (once artifacts are properly retrieved, ivy is not required any more).

The Ivy cachepath documentation similarly states:

If you want to make your build more independent from Ivy, you could consider using the retrieve task. Once the artifacts are properly retrieved, you can use standard Ant path creation which makes Ivy not necessary any more.

So, it would seem a better answer would be to modify Mark's response to something that uses retrieve in conjunction with ant paths. Something along the lines of the following:


Mark's Response (modified)

<configurations>
  <conf name="tasks" description="Ant tasks"/>
</configurations>

<dependencies>
  <dependency org="ant-contrib" name="cpptasks" rev="1.0b5"
      conf="tasks->default"/>
  <dependency org="junit" name="junit" rev="3.8" conf="tasks->default"/>
  ..

In your build.xml file you can create a path from this config

<ivy:retrieve conf="tasks"
     pattern="${dir.where.you.want.taskdef.jars}/[artifact]-[revision].[ext] />

<path id="tasks.path">
  <fileset dir="${dir.where.you.want.taskdef.jars}">
    <include name="**/*.jar"/>
  </fileset>
</path>

<taskdef name="task1" classname="??" classpathref="tasks.path"/>
<taskdef name="task2" classname="??" classpathref="tasks.path"/>

This would even allow you to move the retrieve task into a separate ant file that deals with dependencies. Thereby, you don't have to rely on ivy after your dependencies are retrieved into their directories.

The intention of ivy is that you use it to pull down your jars (resolve & retrieve). Once you have them in place, you can switch back to using standard Ant.


Note: I would just pull these dependencies into the lib directory. That would simplify the retrieve task:

<ivy:retrieve conf="tasks" />

Also Note: visit the 'Path-like Structures' section of this page for more on "standard ant path creation"

OTHER TIPS

The only jar you need in your ant lib is ivy :-)

Declare your dependencies as normal within your ivy.xml file. Make use of a configuration to collectively group the jars associated with ANT tasks:

<configurations>
    <conf name="tasks" description="Ant tasks"/>
</configurations>

<dependencies>
    <dependency org="ant-contrib" name="cpptasks" rev="1.0b5" conf="tasks->default"/>
    <dependency org="junit" name="junit" rev="3.8" conf="tasks->default"/>
    ..

In your build.xml file you can create a path from this configuration

<ivy:resolve/>
<ivy:cachepath pathid="tasks.path" conf="tasks"/>

<taskdef name="task1" classname="??" classpathref="tasks.path"/>
<taskdef name="task2" classname="??" classpathref="tasks.path"/>

I'd use ant to install everything INTO ant =D

Just use depends="init-ant-contrib, init-ivy"

<!-- ANT-CONTRIB Auto Installer -->
<available property="ant-contrib-exists"
           file="${ant.library.dir}/ant-contrib-1.0b3.jar" />
<target name="download-ant-contrib" unless="ant-contrib-exists">
  <mkdir dir="${ant.library.dir}" />
  <get src="http://downloads.sourceforge.net/project/ant-contrib/ant-contrib/1.0b3/ant-contrib-1.0b3-bin.zip?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fant-contrib%2Ffiles%2Fant-contrib%2F1.0b3%2F&amp;use_mirror=cdnetworks-us-1"
       dest="${ant.library.dir}/ant-contrib-1.0b3-bin.zip"
       username="true" />
  <unzip src="${ant.library.dir}/ant-contrib-1.0b3-bin.zip"
         dest="${ant.library.dir}"
         overwrite="no" />
  <move todir="${ant.library.dir}">
    <fileset file="${ant.library.dir}/ant-contrib/*.jar" />
    <fileset file="${ant.library.dir}/ant-contrib/lib/*.jar" />
  </move>
  <delete file="${ant.library.dir}/ant-contrib-1.0b3-bin.zip" />
  <delete dir="${ant.library.dir}/ant-contrib" />
</target>
<target name="init-ant-contrib" depends="download-ant-contrib">
  <taskdef resource="net/sf/antcontrib/antcontrib.properties">
    <classpath>
      <pathelement location="${ant.library.dir}/ant-contrib-1.0b3.jar" />
    </classpath>
  </taskdef>
</target>

<!-- IVY Auto Installer -->
<property name="ivy.install.version" value="2.1.0-rc2" />
<condition property="ivy.home" value="${env.IVY_HOME}">
  <isset property="env.IVY_HOME" />
</condition>
<property name="ivy.home" value="${user.home}/.ant" />
<property name="ivy.jar.dir" value="${ivy.home}/lib" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<available file="${ivy.jar.file}" property="ivy-exists" />
<target name="download-ivy" unless="ivy-exists">
  <mkdir dir="${ivy.jar.dir}" />
  <!-- download Ivy from web site so that it can be used even without any special installation -->
  <get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
       dest="${ivy.jar.file}"
       usetimestamp="true" />
</target>
<target name="init-ivy" depends="download-ivy">
  <!-- try to load ivy here from ivy home, in case the user has not already dropped
              it into ant's lib dir (note that the latter copy will always take precedence).
              We will not fail as long as local lib dir exists (it may be empty) and
              ivy is in at least one of ant's lib dir or the local lib dir. -->
  <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" />
</target>

Now that you have ant-contrib & ivy, everything else should be a simple ivy.xml & ivy-resolve away:

<target name="resolve" depends="init-ivy">
    <ivy:retrieve />
  </target>

I'm sure you can find similar methods of installing whatever ant task you might need.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top