Ivy

Steven J Zeil

Last modified: Nov 20, 2013

Contents:
1. Why Ivy?
2. Getting Started with Ivy

1. Why Ivy?

YAAP[1], Ivy adds the dependency management features pioneered by Maven to ant


Ivy Motivation and Features

2. Getting Started with Ivy

Start with an Ant Project

Again, let’s start with the Code Annotation project.

build.xml0.listing
<project name="codeAnnotation" basedir="." default="build">

  <record name="ant.log" action="start" append="false" />

  <taskdef classpath="JFlex.jar" classname="JFlex.anttask.JFlexTask" name="jflex" /> ➊
    
  <echo>loading build-${os.name}.paths</echo>
  <include file="build-${os.name}.paths"/>  ➋
    

  <target name="generateSource">
    <mkdir dir="src/main/java"/>
    <jflex file="src/main/jflex/code2html.flex"
       destdir="src/main/java"/>
    <jflex file="src/main/jflex/code2tex.flex"
           destdir="src/main/java"/>
    <jflex file="src/main/jflex/list2html.flex"
       destdir="src/main/java"/>
    <jflex file="src/main/jflex/list2tex.flex"
           destdir="src/main/java"/>
  </target>
  

  <target name="compile" depends="generateSource">
    <mkdir dir="target/classes"/>
    <javac srcdir="src/main/java" destdir="target/classes"
       source="1.7" includeantruntime="false"/>
  </target>

  <target name="compile-tests" depends="compile">
    <mkdir dir="target/test-classes"/>
    <javac srcdir="src/test/java" destdir="target/test-classes"
       source="1.7" includeantruntime="false">
      <classpath refid="testCompilationPath"/>
    </javac>
  </target>

  <target name="test" depends="compile-tests">
    <property name="mypath" refid="testExecutionPath"/>
    <echo>testExecutioPath is ${mypath}</echo>
    <echoproperties/>
    <mkdir dir="target/test-results/details"/>
    <junit printsummary="yes" 
       haltonfailure="yes" fork="no"
       >
        <classpath refid="testExecutionPath"/>
      <formatter type="xml"/>
      <batchtest todir="target/test-results/details">
         <fileset dir="target/test-classes">
            <include name="**/*Test*.class"/>
         </fileset>
      </batchtest>
    </junit>
    <junitreport todir="target/test-results">
      <fileset dir="target/test-results/details">
        <include name="TEST-*.xml"/>
      </fileset>
      <report format="frames" todir="target/test-results/html"/>
    </junitreport>
  </target>

  <target name="build"  depends="test">
    <jar destfile="codeAnnotation.jar" basedir="target/classes">
        <manifest>
            <attribute name="Main-Class"
                       value="edu.odu.cs.code2html.Code2HTML"/>
        </manifest>
    </jar>
  </target>

  <target name="clean">
    <delete dir="target"/>
  </target>

  
</project>


Fetching Ivy

Start by having our build file actually load Ivy

build.xml1.listing
<project name="codeAnnotation" basedir="." default="build"
     xmlns:ivy="antlib:org.apache.ivy.ant">

  <record name="ant.log" action="start" append="false" />
    

  <property name="ivy.install.version" value="2.3.0"/>
  <property name="ivy.jar.dir" value="${basedir}/ivy"/>
  <property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar"/>

  <target name="download-ivy" unless="skip.download">
    <mkdir dir="${ivy.jar.dir}"/>
    <echo message="installing ivy..."/>
    <get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar" 
     dest="${ivy.jar.file}" skipexisting="true"/>
  </target>

  <target name="install-ivy" depends="download-ivy" 
      description="--> install ivy">
    <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>

    ⋮

  <target name="generateSource">
    ⋮
  </target>
  

  <target name="compile" depends="generateSource">
    ⋮
</project>


Specifying our Desired Libraries

We list the libraries our project needs in a separate ivy.xml file

<ivy-module version="2.0">
  <dependencies>
    <dependency org="de.jflex" name="jflex" rev="1.4.3"/>
    <dependency org="junit" name="junit" rev="4.10"/>
  </dependencies>
</ivy-module>

This should look familiar to the section from the Maven pom:

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  

Ivy is Often Simpler

Although the handling of Junit is similar, compare the handling of JFlex in Ivy:

<ivy-module version="2.0">
  <dependencies>
    <dependency org="de.jflex" name="jflex" rev="1.4.3"/>
    <dependency org="junit" name="junit" rev="4.10"/>
  </dependencies>
</ivy-module>

to Maven:

  <build>
    ⋮
    <pluginManagement>
    <plugins>
      <plugin>
        <groupId>de.jflex</groupId>
        <artifactId>maven-jflex-plugin</artifactId>
        <version>1.4.3</version>
        <executions>
          <execution>
            <goals>
              <goal>generate</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </pluginManagement>
  </build>
  

Maven makes a distinction between simple library dependencies and plugins.


Invoking Ivy

Once Ivy is installed, we can invoke it:

build.xml2.listing
<project name="codeAnnotation" basedir="." default="build"
     xmlns:ivy="antlib:org.apache.ivy.ant">
     ⋮

  <target name="resolve-ivy" depends="install-ivy">
    <ivy:retrieve/>   ➊
    <echo>ivy.default.ivy.user.dir is ${ivy.default.ivy.user.dir}</echo>
    <taskdef classpath="JFlex.jar" 
         classname="JFlex.anttask.JFlexTask" name="jflex" /> ➋
  </target>

  <target name="generateSource" depends="resolve-ivy">   ➍
    <mkdir dir="target/gen/java"/>
    <jflex file="src/main/jflex/code2html.flex"    ➌
       destdir="target/gen/java"/>
    <jflex file="src/main/jflex/code2tex.flex"
       destdir="target/gen/java"/>

        ⋮


Set Up Classpaths

… to use the newly downloaded libraries.

build.xml3.listing
<project name="codeAnnotation" basedir="." default="build"
     xmlns:ivy="antlib:org.apache.ivy.ant">

  <record name="ant.log" action="start" append="false" />
    
  <path id="testCompilationPath">
    <fileset dir="lib" includes="*.jar"/>
    <pathelement path="target/classes"/>
  </path>

  <path id="testExecutionPath">
    <fileset dir="lib" includes="*.jar"/>
    <pathelement path="target/classes"/>
    <pathelement path="target/test-classes"/>
  </path>


  <property name="ivy.install.version" value="2.3.0"/>
  <property name="ivy.jar.dir" value="${basedir}/ivy"/>
  <property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar"/>
  <property name="build.dir" value="build"/>
  <property name="src.dir" value="src"/>

  <target name="download-ivy" unless="skip.download">
    <mkdir dir="${ivy.jar.dir}"/>
    <echo message="installing ivy..."/>
    <get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar" 
     dest="${ivy.jar.file}" usetimestamp="true"/>
  </target>

  <target name="install-ivy" depends="download-ivy" 
      description="--> install ivy">
    <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>

  <target name="resolve-ivy" depends="install-ivy">
    <ivy:retrieve/>
    <echo>ivy.default.ivy.user.dir is ${ivy.default.ivy.user.dir}</echo>
    <taskdef classpath="JFlex.jar" 
         classname="JFlex.anttask.JFlexTask" name="jflex" />
  </target>

  <target name="generateSource" depends="resolve-ivy">
    <mkdir dir="target/gen/java"/>
    <jflex file="src/main/jflex/code2html.flex"
       destdir="target/gen/java"/>
    <jflex file="src/main/jflex/code2tex.flex"
       destdir="target/gen/java"/>
    <jflex file="src/main/jflex/list2html.flex"
       destdir="target/gen/java"/>
    <jflex file="src/main/jflex/list2tex.flex"
       destdir="target/gen/java"/>
  </target>
  

  <target name="compile" depends="generateSource">
    <mkdir dir="target/classes"/>
    <javac srcdir="target/gen/java" destdir="target/classes"
       source="1.6" includeantruntime="false"/>
    <javac srcdir="src/main/java" destdir="target/classes"
       source="1.6" includeantruntime="false"/>
  </target>

  <target name="compile-tests" depends="compile">
    <mkdir dir="target/test-classes"/>
    <javac srcdir="src/test/java" destdir="target/test-classes"
       source="1.6" includeantruntime="false">
      <classpath refid="testCompilationPath"/>
    </javac>
  </target>

  <target name="test" depends="compile-tests">
    <mkdir dir="target/test-results/details"/>
    <junit printsummary="yes" 
       haltonfailure="yes" fork="no"
       >
      <classpath refid="testExecutionPath"/>
      <formatter type="xml"/>
      <batchtest todir="target/test-results/details">
         <fileset dir="target/test-classes">
            <include name="**/*Test*.class"/>
         </fileset>
      </batchtest>
    </junit>
    <junitreport todir="target/test-results">
      <fileset dir="target/test-results/details">
        <include name="TEST-*.xml"/>
      </fileset>
      <report format="frames" todir="target/test-results/html"/>
    </junitreport>
  </target>

  <target name="build"  depends="test">
    <jar destfile="codeAnnotation.jar" basedir="target/classes">
        <manifest>
              <attribute name="Main-Class"
                value="edu.odu.cs.code2html.Code2HTML"/>
        </manifest>
    </jar>
    <zip destfile="target/codeAnnotation-src.zip">
      <fileset dir=".">
        <include name="*.xml"/>
        <include name="test.cpp"/>
        <include name="*.css.cpp"/>
        <include name="src/**/*"/>
        <exclude name="**/*~"/>
        <exclude name="target/**/*"/>
      </fileset>
    </zip>
  </target>

  <target name="clean">
    <delete dir="target"/>
  </target>

  <target name="cleaner" depends="clean">
    <delete dir="lib"/>
  </target>

  <target name="cleanest" depends="cleaner">
    <delete dir="ivy"/>
  </target>
  
</project>


  1. Yet Another Apache Project  ↩