如何在Ant构建文件中指定JAR文件的路径?

8
我正在从ant构建脚本中执行大量的scp、sshexec和其他远程命令。如果ant lib目录中没有jsch.jar,则这些命令无法正常工作。为了使其正常工作,我将JAR文件复制到ant lib目录中,但这不是一个好的解决方案,因为任何想要运行该脚本的人都必须做同样的事情。要从Teamcity运行ant目标,我们必须明确设置lib文件的路径。
有没有一种方法可以在ant构建XML本身中指定JAR的路径?

你测试过你的Ant代码示例吗?我不明白为什么它不能工作。我用同样的方式处理其他任务。 - Robert
我并不是说它不能工作,它确实可以工作,但我必须将jsch.jar添加到ant lib目录中,而我想避免这样做。如果我的问题没有表述清楚,我很抱歉。我们有这样的任务{ <scp todir="user1:pass1@server1:/tmp" trust="true" > <fileset dir="dir1"> <include name="file.txt" /> </fileset> </scp> }为了使其工作,我必须手动将jsch.jar添加到ant lib中。我能否通过在构建文件中放置某些内容来避免这种情况? - Ravi
如果jsch.jar不在lib目录中,您删除的代码片段也可以工作。然后,您必须确保指定正确的相对或绝对路径。 - Robert
3个回答

5
感谢大家的回答。我通过类加载器任务成功地使它工作了。这就是我所做的。
<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>

如您所见,我没有为“Test”目标指定任何依赖目标,它可以正常工作。它使用类加载器,将jsch.jar附加到系统类加载器中。


我认为类加载器并不是必要的。在文件顶部进行路径声明,再结合 taskdef ant 任务上的 classpathref 属性即可正常工作。 - Mark O'Connor
需要重新声明taskdef,为此我必须从lib目录中删除ant-jsch.jar并添加新的scp和sshexec taskdef。 - Ravi
这个解决方案非常有效。ClassLoader的JAR包和相关信息可以在http://enitsys.sourceforge.net/ant-classloadertask/找到。 - zombat

2

一个可能的解决方法是使用-lib命令行选项告诉ant在哪里查找额外的jar包。或许你可以创建一个包装脚本,调用设置了这个选项的ant

另一种方法是将ant-jsch.jar文件(这是随ant一起提供的定义任务的jar,而不是您需要单独下载的jsch.jar文件)移出ant lib目录,并为您的ssh任务创建一个独立于内置任务的taskdef,然后将此任务的类路径设置为jsch.jarant-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>

我不确定这会不会帮到你,因为它还涉及对lib目录进行更改。
据我所知,在一般情况下,目前无法在构建文件本身中指定内置任务所需的额外jar。当然也有一些特殊情况,比如junit。

如果任务需要多个JAR,为什么不将所有JAR合并成一个JAR以避免问题呢? - Robert
1
我不想更改ant lib目录,因为我无法对其进行任何控制。在那种情况下,这个选项行不通。 - Ravi

1
为了确保您的构建更具跨平台性,我建议使用依赖管理。ivy插件可以在构建时自动安装构建插件的版本。
这种方法意味着您需要安装到ANT lib中的最后一个jar文件是ivy-2.2.0.jar :-)
首先,在文件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>

在你的 build.xml 中运行 ivy,并使用它来根据 ivy 配置填充自定义类路径:
<target name='init' description='Resolve project dependencies and set classpaths'>
    <ivy:resolve/>
    <ivy:cachepath pathid="anttask.path" conf="anttask"/>
</target>

最后,在您的构建中的其他位置,使用由ivy自动填充的类路径声明您的ANT任务。
<target name='dosomething' depends="init">
    <taskdef name="sshexec" 
             classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec"
             classpathref="anttask.path"/>
    ..
    ..
</target>

这种方法适用于所有ANT插件,其中大多数都可以在中央Maven存储库中获得。第二个好处是可以轻松升级所有构建中的插件版本。


这并不能解决一些jar需要存在ant的lib目录中以满足类加载的要求的问题。实际的ant任务是在ant-jsch.jar中定义的,这个jar是随着ant一起提供的,而不是通过单独下载jsch.jar得到的。问题在于如何让ant-jsch.jar中的类能够看到jsch.jar。或者是我漏掉了什么? - matt
请查看taskdef任务上的"classpathref"属性。它允许你在声明任务时指定要使用的类路径。Ivy提供的帮助是在构建时下载并填充该类路径的能力,这就是Maven构建工具所做的所有插件都被下载的原因。 - Mark O'Connor
我非常喜欢你的方法,但是在这里每个任务都必须首先调用init任务depends="init"。我正在寻找更像“一次更改,适用于所有”的选项。 - Ravi
init任务将下载ivy文件中指定的所有jar包。然后,您可以立即声明任务,或者像上面的示例一样等到需要它们时再声明。我的示例只包含一个依赖项。一个典型的构建项目需要10-30个jar包,不仅用于任务,还用于其他框架,如Spring和Hibernate。请有空时看看Maven构建工具,它会向您介绍有关构建管理的新思想。ivy插件使您能够支持这些功能,同时仍然使用ANT作为主要构建工具。 - Mark O'Connor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接