How can I specify the path of a JAR in an ant buildfile?
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.
Ravi
Updated on June 12, 2022Comments
-
Ravi almost 2 years
I am executing lot of
scp
andsshexec
and other remote commands from an ant build script. These commands don't work ifjsch.jar
isn't in the antlib
directory. To make it work, I copied the JAR into the antlib
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 about 13 yearsIf there are troubles if the task requires more than one JAR why not simply mering all JARs into one JAR?
-
matt about 13 yearsThis 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 about 13 yearsCheckout 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 about 13 yearsI 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 about 13 yearsI 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 about 13 yearsThe 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 about 13 yearsI 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 about 13 yearstaskdef 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 almost 12 yearsThis solution worked great. The classloader jar and information can be found at enitsys.sourceforge.net/ant-classloadertask