How can I specify the path of a JAR in an ant buildfile?

11,216

Solution 1

Thanks all for your answers. I am managed to get it work with classloader task. This is what I did.

<project basedir="." >
  <property environment="env"/>

  <taskdef resource="net/jtools/classloadertask/antlib.xml">
    <classpath>
      <fileset dir="${basedir}/lib" includes="ant-classloader*.jar"/>
    </classpath>
  </taskdef>

  <!--Add JSCH jar to the classpath-->
  <classloader loader="system">
    <classpath>
      <fileset dir="${basedir}/lib" includes="jsch*.jar"/>
      </classpath>
  </classloader>

  <target name="Test">
      <scp todir="user1:pass1@server1:/tmp" trust="true" >
        <fileset dir="dir1">
          <include name="test.txt" />
        </fileset>
      </scp>
   </target>
</project>

As you can see here, I didn't have to give any dependant target for my "Test" target, it just works. It uses classloader, which appends jsch.jar to the system classloader.

Solution 2

One possible work around would be to use the -lib command line option to tell ant where to look for additional jars. Perhaps you could create a wrapper script that calls ant with this option set.

Another way would be to move the ant-jsch.jar file (this is the jar that comes with ant that defines the tasks, not the jsch.jar file you need to download separately) out of your ant lib directory, and create a taskdef for your ssh task separate to the built in one, then set the classpath for this task to the jsch.jar and the ant-jsch.jar:

<taskdef name="sshexec"
  classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec">
  <classpath>
    <pathelement location="jsch-0.1.44.jar"/>
    <pathelement location="ant-jsch.jar" />
  </classpath>
</taskdef>

I'm not sure this will help you though, since it also involves making changes to the lib directory.

As far as I'm aware, it's not currently possible to specify the extra jars required for the built in tasks in the build file itself in general. There are some special cases, like junit for instance.

Solution 3

To ensure your build is more cross platform I'd suggest using dependency management. The ivy plug-in can automatically install the version of your build's plugin at build-time.

This approach means the last jar you'll ever need to install into your ANT lib is ivy-2.2.0.jar :-)

First declare your project's dependencies in the file ivy.xml

<ivy-module version="2.0">
    <info organisation="com.myspotontheweb" module="demo"/>
    <configurations>
        <conf name="anttask" description="Jars implementing ANT tasks"/>
    </configurations>
    <dependencies>
        <dependency org="com.jcraft" name="jsch" rev="0.1.42" conf="anttask->default"/>
    </dependencies>
</ivy-module>

Within your build.xml run ivy and use it to populate a custom classpath based on the ivy configuration:

<target name='init' description='Resolve project dependencies and set classpaths'>
    <ivy:resolve/>
    <ivy:cachepath pathid="anttask.path" conf="anttask"/>
</target>

Finally, elsewhere in your build declare your ANT tasks using the class path now automatically populated by ivy.

<target name='dosomething' depends="init">
    <taskdef name="sshexec" 
             classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec"
             classpathref="anttask.path"/>
    ..
    ..
</target>

This approach works for all ANT plug-ins, most of which are available in the central Maven repository. The second benefit is that it's easy to upgrade the plug-in versions across all builds.

Share:
11,216
Ravi
Author by

Ravi

Updated on June 12, 2022

Comments

  • Ravi
    Ravi almost 2 years

    I am executing lot of scp and sshexec and other remote commands from an ant build script. These commands don't work if jsch.jar isn't in the ant lib directory. To make it work, I copied the JAR into the ant lib directory, but this is not a good solution, as anyone else wanting to run the script would have to do the same thing. To run the ant target from Teamcity, we will have to explicitly set the path of the lib file.

    Is there a way I can specify the path of the JAR in the ant build XML itself?

  • Robert
    Robert about 13 years
    If there are troubles if the task requires more than one JAR why not simply mering all JARs into one JAR?
  • matt
    matt about 13 years
    This doesn't fix the problem of some jars needing to be in ants lib dir to satisfy the classloading requirements though. The actual ant task is defined in ant-jsch.jar which comes with ant, not in the jsch.jar downloaded separately. The problem is making jsch.jar visible to the classes in ant-jsch.jar. Or am I missing something?
  • Mark O'Connor
    Mark O'Connor about 13 years
    Checkout the "classpathref" attribute on the taskdef task. It allows you to specify the class path to be used when declaring your task. The assistance ivy offers is the ability to download and populate that class path at build time. This is what the Maven build tool does, all it's plugins are downloaded.
  • Ravi
    Ravi about 13 years
    I don't want to make changes to the ant lib directory as I don't have any control on it. This option wouldn't work in that scenario
  • Ravi
    Ravi about 13 years
    I quite like your approach, but again here each task will have to have call the init task first depends="init". I am looking for the option which is more like "change once and work for all" approach.
  • Mark O'Connor
    Mark O'Connor about 13 years
    The init task would download all jars you specify in the ivy file. You then declare the tasks immediately or wait until you need them as in my example above. My example contains a single dependency. A typical build project would require 10-30 jars, not just for tasks, but for other frameworks like Spring and Hibernate. Please look at the Maven build tool some day. It will introduce you to new ideas on build management. The ivy plug-in enables to you support these yet keep using ANT as your primary build tool.
  • Mark O'Connor
    Mark O'Connor about 13 years
    I don't think the classloader is necessary. A path declaration at the top of your file would have worked fine, combined with a classpathref attribute on taskdef ant task.
  • Ravi
    Ravi about 13 years
    taskdef would have to be declared again, for which I would have to remove the ant-jsch.jar from lib directory and add nw taskdef for scp and sshexec.
  • zombat
    zombat almost 12 years
    This solution worked great. The classloader jar and information can be found at enitsys.sourceforge.net/ant-classloadertask