如何为Ant构建配置Ivy

18

我目前的ANT_HOME位于/home/<myuser>/ant/1.8.4/ant-1.8.4

我刚下载了包含其依赖项的Apache Ivy tarball。 我将其提取到/home/<myuser>/ivy/2.3.0-rc1/ivy-2.3.0-rc1

然后,我将/home/<myuser>/ivy/2.3.0-rc1/ivy-2.3.0-rc1/lib/*.jar复制到ANT_HOME/lib。 如果我对Ant如何使用插件/扩展的理解正确,则Ant现在应该能够在运行时访问所有Ivy的任务。

我的下一个问题是,在Ant构建文件中如何定义Ivy任务? 假设我想使用ivy-retrieveivy-resolveivy-publish任务。 当我从命令行运行我的Ant构建时,我需要进行哪些配置(在XML中)才能使这些任务正常工作(我不会通过Ant-Eclipse插件进行构建)。 提前致谢!

2个回答

65
首先,您需要定义一个<taskdef>来指向Ivy任务。
<property environment="env"/>
<property name="ivy.home" value="${env_IVY_HOME}"/>

<taskdef resource="org/apache/ivy/ant/antlib.xml">
    <classpath>
        <fileset dir="${ivy.home}">
            <include name="*.jar"/>
        </fileset>
    </classpath>
</taskdef>

那将使您可以访问Ivy任务。您可以像这样使用这些任务:
<cachepath pathid="main.classpath" conf="compile"/>

问题在于你的Ivy任务名称可能会与其他Ant任务冲突。例如,有一个Ivy任务<report>。为了解决这个问题,你可以创建一个Ivy命名空间。要做到这一点,你需要在<project>实体中放置一个引用来指向你的命名空间,就像这样:
<project name="my.proj" default="package" basedir="."
    xmlns:ivy="antlib:org.apache.ivy.ant"/>

现在,当你定义Ivy任务时,可以使用antlib:org.apache.ivy.ant引用你的ivy命名空间。与之前相同的taskdef,但需要加上一个uri字段:

<property environment="env"/>
<property name="ivy.home" value="${env_IVY_HOME}"/>

<taskdef resource="org/apache/ivy/ant/antlib.xml"
    uri="antlib:org.apache.ivy.ant">
    <classpath>
        <fileset dir="${ivy.home}">
            <include name="*.jar"/>
        </fileset>
    </classpath>
</taskdef>

顺便说一下,那个uri没有什么特别的。我也可以这样做:

<project name="my.proj" default="package" basename="."
   xmlns:ivy="pastrami:with.mustard">

[...]
<taskdef resource="org/apache/ivy/ant/antlib.xml"
    uri="pastrami:with.mustard">
    <classpath>
        <fileset dir="${ivy.home}">
            <include name="*.jar"/>
        </fileset>
    </classpath>
</taskdef>

现在你可以在任务名前加上“ivy:”。这样做代替了原来的方式:
<cachepath pathid="main.classpath" conf="compile"/>

您现在可以这样做:

<ivy:cachepath pathid="main.classpath" conf="compile"/>

这就是如何获取您的Ivy Ant任务的方法。
现在,您已经可以访问您的Ivy Ant任务,您需要定义一个ivysettings.xml文件,并使用任务指向它:
 <ivy:settings file="${ivy.home}/ivysettings.xml"/>

在Ivy中有一个默认的ivysettings.xml文件,它会将您指向全球范围内的Maven存储库系统。如果您没有公司级别的Maven存储库,则可以使用默认的ivysettings.xml文件:

<ivy:settings/>

这很简单。

完成上述步骤后,您需要读取并解析您的ivy.xml文件,该文件通常位于项目根目录中,与build.xml文件在同一目录中。

基本上,您的ivy.xml文件包含了您想要引入项目中的第三方jar包的引用。例如:

<dependencies>
    <dependency org="log4j"  name="log4j" rev="1.2.17" conf="compile->default"/>
    <dependency org="junit"  name="junit" rev="4.10" conf="test->default"/>
</dependencies>

这段话的意思是,我需要 log4j.jar(版本为1.2.17)进行编译(包括编译测试代码),还需要 junit.jar(版本为4.10)用于测试代码的编译。 compile->default 将我的 compile 配置映射到 Maven 的 default 配置(表示我只需要 Jar 包及其可能依赖的其他 Jar 包)。
我的 compile 配置从哪里来?我在 ivy.xml 中定义了它。有十个标准配置,也要写入你的 ivy.xml 文件。
<configurations>
  <conf name="default" visibility="public" description="runtime dependencies and master artifact can be used with this conf" extends="runtime,master"/>
  <conf name="master" visibility="public" description="contains only the artifact published by this module itself, with no transitive dependencies"/>
  <conf name="compile" visibility="public" description="this is the default scope, used if none is specified. Compile dependencies are available in all classpaths."/>
  <conf name="provided" visibility="public" description="this is much like compile, but indicates you expect the JDK or a container to provide it. It is only available on the compilation classpath, and is not transitive."/>
  <conf name="runtime" visibility="public" description="this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath." extends="compile"/>
  <conf name="test" visibility="private" description="this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases." extends="runtime"/>
  <conf name="system" visibility="public" description="this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository."/>
  <conf name="sources" visibility="public" description="this configuration contains the source artifact of this module, if any."/>
  <conf name="javadoc" visibility="public" description="this configuration contains the javadoc artifact of this module, if any."/>
   <conf name="optional" visibility="public" description="contains all optional dependencies"/>
 </configurations>

你可以使用任何配置名称,但这些名称对应于默认的Maven配置,并且被广泛使用。
一旦你定义了你的ivy.xml文件,你可以使用来解决你的依赖关系:
<ivy:resolve/>

所以,我们有以下内容:
  1. 如何在您的build.xml中使用<taskdef>来将Ivy Ant任务合并到您的构建中。
  2. 如何使用Ivy Ant任务<ivy:settings>来配置Ivy。
  3. 如何使用<ivy:resolve/>读取您的ivy.xml文件并解析第三方jar依赖项。
现在,您可能想要实际使用这些jar文件。有三种方法可以做到这一点:
 <ivy:cachepath pathid="main.classpath" conf="compile"/>
<ivy:retrieve/>任务将下载您在ivy.xml文件的compile配置中定义的所有依赖项。 如果您需要一个文件集,可以使用此任务。 通常与<copy>任务一起使用以将文件复制到目标位置。

示例:

<ivy:retrieve pattern="lib/[artifact].[ext]"/>

这将下载所有依赖项并将它们放置在lib/目录下。

 <ivy:cachefileset setid="compile.fileset" conf="compile"/>

在这种情况下,它将创建一个具有 compile.fileset refid 的文件集。
有时您需要将jar包引入您的项目中。例如,如果您创建了一个war或ear文件,您想要将您的jar包封装起来。在这种情况下,您可以使用以下方法:
<property name="lib.dir" value="${target.dir}/lib"/>
<ivy:retrieve pattern="${lib.dir}/[artifact].[ext]"
     conf="runtime"/>

那将把你的jar文件获取到${lib.dir}目录中,这样你就可以在wars或ears中包含它们。
抱歉回答比较长,但需要涵盖很多步骤。我强烈推荐Manning出版社的书籍Ant in Action,其中有一整章介绍了Ivy。

3
这是我所提出或遇到的任何与常春藤相关问题中最全面的答案,我希望我能给它更多的赞。感谢您抽出时间来帮助我,这太完美了。一个快速的后继问题(如果可以):我计划拥有自己的托管存储库,可能由Artifactory管理。每次我使用Ivy时,我看到我的同事将他们的conf属性定义为conf="*->*"conf=compile->default,但似乎没有人清楚这些内容的作用和原因... - IAmYourFaja
你提到它是本地Ivy配置(ivy.xml)和解决对应仓库之间的映射,甚至还慷慨地展示了compile配置可能看起来像什么(与test配置相比)。但是在存储库端(“箭头”操作符的右侧)呢? "*->*"映射到什么?“default”呢?只是好奇,因为无论我读多少次Ivy文档,都似乎无法理解。再次感谢您的所有帮助! - IAmYourFaja
在Ivy中没有标准配置文件。您必须在您的ivy.xml文件中定义您的配置文件。我在文章中提到的标准配置映射到Maven的_scopes_。 我可以在我的“ivy.xml”中定义一个单独的配置,或者我可以添加我上面没有提到的配置。例如,有些人在“ivy.xml”中添加了“generated-sources”配置文件,用于axis2和WSDL文件等。问题在于您必须将您的配置映射到存储库的配置。我从未尝试过*->*。我猜它会将您“ivy.xml”中的所有配置文件映射到所有存储库配置文件中。我得试试看。 - David W.
在2015年,这仍然是关于Ivy Ant任务最全面和清晰的教程。 - Sharon Ben Asher

14

David给出了一个很好的答案,但我想指出taskdef不是必需的。 只要ivy.jar在预期位置,ANT文件顶部的命名空间声明就足够了:

<project ..... xmlns:ivy="antlib:org.apache.ivy.ant">
更详细的内容建议阅读关于ANT libs如何工作的说明。
以下答案提供了更多“设置 Ivy”的建议:

1
如果ivy.jar在ant_home/lib中,那么这就是正确且简单的答案。 - oers

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