Welcome to the official Ivy documentation.
If you browse this documentation from your installation of ivy, you can also check the online version for latest updates.
The online version of this documentation is updated periodically, especially when new features are added during development. So if you find something documented here not available in your version of ivy, it may be because it is available only with the latest download.
If you want to view the whole documentation in a single printer-friendly page, please use the printer-friendly link at the bottom of any documentation page.
This documentation is decomposed in 3 main parts:
The best way to learn is to practice ! That's what the ivy tutorials will help you to do to discover some of the great ivy features.
But before starting the tutorials, make sure you have properly installed ivy.
The following tutorials are available:
Quick Start will guide you through your very first steps with ivy.
Using IvyRep will show you the out of the box power of ivy + ivyrep.
Configuring default resolver will give you a better understanding of the default configuration and show you how to customize it to your needs.
Multiple Resolvers will teach you how to configure Ivy to find its dependencies in multiple places.
Dual Resolver will help you configure ivy to find ivy files in one place and artifacts in another.
Project Dependencies will finally makes you touch the interest of using ivy in multi project environment.
Using Ivy Configurations will show how to use configurations in ivy file to define set of artifacts.
Building a repository will show how to build your own enterprise repository.
I:\hello-ivy>ant Buildfile: build.xml resolve: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: no configuration file found, using default... :: resolving dependencies :: jayasoft/hello-ivy-working@xmen confs: [default] downloading http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-2.0.jar(2.0) ... ..................................... (165kB) [SUCCESSFUL ] apache/commons-lang-2.0/commons-lang.jar[jar] (4688ms) :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 1 | 1 | 0 | 0 || 1 | 1 | --------------------------------------------------------------------- :: retrieving :: jayasoft/hello-ivy confs: [default] 1 artifacts copied, 0 already retrieved run: [mkdir] Created dir: I:\hello-ivy\build [javac] Compiling 1 source file to I:\hello-ivy\build [java] standard message : hello ivy ! [java] capitalized by org.apache.commons.lang.WordUtils : Hello Ivy ! BUILD SUCCESSFUL Total time: 8 seconds
I:\hello-ivy>ant Buildfile: build.xml resolve: :: resolving dependencies :: jayasoft/hello-ivy-null :: [default] :: resolution report :: [default] jayasoft/hello-ivy-working@rahan: 1 artifacts (0 downloaded) :: retrieving :: jayasoft/hello-ivy :: [default] run: [java] standard message : hello ivy ! [java] capitalized by org.apache.commons.lang.WordUtils : Hello Ivy ! BUILD SUCCESSFUL Total time: 1 second
I:\ivyrep>ant Buildfile: build.xml resolve: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: no configuration file found, using default... :: resolving dependencies :: jayasoft/ivyrep-example-working@xmen confs: [default] downloading http://www.ibiblio.org/maven/commons-cli/jars/commons-cli-1.0.jar(1.0) ... ...... (31kB) [SUCCESSFUL ] apache/commons-cli-1.0/commons-cli.jar[jar] (1437ms) downloading http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-2.0.jar(2.0) ... ..................................... (165kB) [SUCCESSFUL ] apache/commons-lang-2.0/commons-lang.jar[jar] (5640ms) downloading http://www.ibiblio.org/maven/commons-logging/jars/commons-logging-1.0.jar(1.0) ... ..... (21kB) [SUCCESSFUL ] apache/commons-logging-1.0/commons-logging.jar[jar] (1250ms) :: resolution report :: :: evicted modules: apache/commons-lang-1.0 by [apache/commons-lang-2.0] in [default] --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 4 | 3 | 2 | 1 || 3 | 3 | --------------------------------------------------------------------- :: retrieving :: jayasoft/ivyrep-example confs: [default] 3 artifacts copied, 0 already retrieved run: [mkdir] Created dir: I:\ivyrep\build [javac] Compiling 1 source file to I:\ivyrep\build [java] standard message : hello ivy ! [java] capitalized by org.apache.commons.lang.WordUtils : Hello Ivy ! BUILD SUCCESSFUL Total time: 16 seconds
I:\ivyrep>ant Buildfile: build.xml resolve: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: no configuration file found, using default... :: resolving dependencies :: jayasoft/ivyrep-example-working@xmen confs: [default] :: resolution report :: :: evicted modules: apache/commons-lang-1.0 by [apache/commons-lang-2.0] in [default] --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 4 | 0 | 0 | 1 || 3 | 0 | --------------------------------------------------------------------- :: retrieving :: jayasoft/ivyrep-example confs: [default] 0 artifacts copied, 3 already retrieved run: [java] standard message : hello ivy ! [java] capitalized by org.apache.commons.lang.WordUtils : Hello Ivy ! BUILD SUCCESSFUL Total time: 2 seconds
Until Ivy 1.2a, the default resolver was a simple ivyrep resolver, with only a small number of possibilities of configuration. Whenever you wanted to do something slightly more complicated than looking for ivy files on ivyrep and artifacts on ibiblio, you had to write your own ivyconf file (see other tutorials and configuration reference for details about this).
Ivy 1.3 introduces a new default configuration, fully compatible pre 1.3 one, but a lot more configurable.
This default configuration mainly consists of 3 kind of repositories:
Note that if you work alone, the distinction between local and shared repository is not very important, but there are some things to know to distinguish them.
Now let's describe each of these repositories concept in more details. We will describe how they are setup physically later.
The local repository is particularly useful when you want to do something without being disturb by anything else happening in the environment. This means that whenever ivy is able to locate a module in this repository it will be used, no matter of what is available in others.
For instance, if you have a module declaring a dependency on the module foo in revision latest.integration, then if a revision of foo is found in the local repository, it will be used, even if a more recent revision is available in other repositories.
This may be disturbing for some of you, but imagine you have to implement a new feature on a project, and in order to achieve that you need to modify two modules: you add a new method in module foo and exploit this new method in module bar. Then if you publish the module foo to your local repository, you will be sure to get it in your bar module, even if someone else publish a new revision of foo in the shared repository (this revision not having the new method you are currently adding).
But be careful, when you have finished your development and publish it on the shared you will have to clean your local repository to benefit from new versions published in the shared repository.
Note also that modules found in the local repository must be complete, i.e. they must provide both a module descriptor and the published artifacts.
As its name suggest, the shared repository is aimed to be shared among a whole development team. It is a place where you can publish your team private modules for instance, and it's also a place where you can put modules not available in the public repository (sun jars, for instance), or simply not accurate (bad or incomplete module descriptors for instance).
Note that modules can be split across the shared repository and the public one: you can have the module descritor in the shared repository and the artifacts in the public one, for instance.
The public repository is the place where most modules can be found, but which sometimes lack the information you need. It's usually a repository available through an internet connection only, even if this is not mandatory.
Now that we have seen the objective of each of the three repositories, let's see how they are setup and how to configure them to fit your needs.
First, several repositories uses the same root in your filesystem. Referenced as ${ivy.default.ivy.user.dir}, this is by default the directory .ivy in your user home.
Note that several things can be done by setting ivy variable. To set them without defining your own ivyconf.xml file, you can:
For instance:
<target name="resolve">
<property name="ivy.default.ivy.user.dir" value="/path/to/ivy/user/dir"/>
<ivy:resolve />
</target>
By default, the local repository lies in ${ivy.default.ivy.user.dir}/local. This is usually a good place, but you may want to modify it however. No problem, you just have to set the following ivy variable to the directory you want to use: ivy.local.default.root
. For instance:
ivy.local.default.root=/opt/ivy/repository/local
.
If you already have something you would like to use as your local repository, you may also want to modify the layout of this repository. Once again, two variables are available for that:
ivy.local.default.ivy.pattern
gives the pattern to find ivy files
ivy.local.default.artifact.pattern
gives the pattern to find artifacts
For example:
ivy.local.default.root=/opt/ivy/repository/local
ivy.local.default.ivy.pattern=[module]/[revision]/ivy.xml
ivy.local.default.artifact.pattern=[module]/[revision]/[artifact].[ext]
By default, the shared repository lies in ${ivy.default.ivy.user.dir}/shared. This is fine if you work alone, but the shared repository is supposed to be, mmm, shared ! So changing this directory is often required, and it is usually modified to point to a shared directory. You can use ivy.shared.default.root
variable to specify in a new directory. Moreover, you can also configure the layout with variables similar to the one for the local repository:
ivy.shared.default.ivy.pattern
gives the pattern to find ivy files
ivy.shared.default.artifact.pattern
gives the pattern to find artifacts
For example:
ivy.shared.default.root=/opt/ivy/repository/shared
ivy.shared.default.ivy.pattern=[organisation]/[module]/[revision]/ivy.xml
ivy.shared.default.artifact.pattern=[organisation]/[module]/[revision]/[artifact].[ext]
By default, the public repository is ivyrep. To change the setting of this resolver, you can use the standard way to configure ivyrep:
ivy.ivyrep.default.ivy.root
specify the root for ivy files
ivy.ivyrep.default.ivy.pattern
specify the layout for ivy files
ivy.ivyrep.default.artifact.root
specify the root for artifacts
ivy.ivyrep.default.artifact.pattern
specify the layout for artifacts
For instance:
ivy.ivyrep.default.ivy.root=http://myserver/ivy/
ivy.ivyrep.default.artifact.root=http://myserver/ivy/
OK, so we have seen how to easily change the settings of the three main repositories. But what if I want my shared repository is on a web server ? What if the public repository is not compatible with ivyrep ? What if ...
Everything can be changed in the default configuration, for sure, you can even do your own configuration. But you can also benefit from a part of the default configuration without writing a complete one.
But before explaining how, you will need to have a quick overview of how ivy is configured by default.
By default, ivy is configured using an ivyconf.xml which is packaged in the ivy jar. Here is this ivyconf file:
<ivyconf>
<conf defaultResolver="default"/>
<include url="${ivy.default.conf.dir}/ivyconf-public.xml"/>
<include url="${ivy.default.conf.dir}/ivyconf-shared.xml"/>
<include url="${ivy.default.conf.dir}/ivyconf-local.xml"/>
<include url="${ivy.default.conf.dir}/ivyconf-main-chain.xml"/>
<include url="${ivy.default.conf.dir}/ivyconf-default-chain.xml"/>
</ivyconf>
<ivyconf>
<conf defaultResolver="default"/>
<include url="http://myserver/ivy/myivyconf-public.xml"/>
<include url="${ivy.default.conf.dir}/ivyconf-shared.xml"/>
<include url="${ivy.default.conf.dir}/ivyconf-local.xml"/>
<include url="${ivy.default.conf.dir}/ivyconf-main-chain.xml"/>
<include url="${ivy.default.conf.dir}/ivyconf-default-chain.xml"/>
</ivyconf>
<ivyconf>
<resolvers>
<filesystem name="public">
<ivy pattern="/path/to/my/public/rep/[organisation]/[module]/ivy-[revision].xml" />
<artifact pattern="/path/to/my/public/rep/[organisation]/[module]/[artifact]-[revision].[ext]" />
</filesystem>
</resolvers>
</ivyconf>
<ivyconf>
<resolvers>
<ivyrep name="public"/>
</resolvers>
</ivyconf>
<ivyconf>
<property name="ivy.shared.default.root" value="${ivy.default.ivy.user.dir}/shared" override="false"/>
<property name="ivy.shared.default.ivy.pattern" value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]" override="false"/>
<property name="ivy.shared.default.artifact.pattern" value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]" override="false"/>
<resolvers>
<filesystem name="shared">
<ivy pattern="${ivy.shared.default.root}/${ivy.shared.default.ivy.pattern}" />
<artifact pattern="${ivy.shared.default.root}/${ivy.shared.default.artifact.pattern}" />
</filesystem>
</resolvers>
</ivyconf>
<ivyconf>
<property name="ivy.local.default.root" value="${ivy.default.ivy.user.dir}/local" override="false"/>
<property name="ivy.local.default.ivy.pattern" value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]" override="false"/>
<property name="ivy.local.default.artifact.pattern" value="[organisation]/[module]/[revision]/[type]s/[artifact].[ext]" override="false"/>
<resolvers>
<filesystem name="local">
<ivy pattern="${ivy.local.default.root}/${ivy.local.default.ivy.pattern}" />
<artifact pattern="${ivy.local.default.root}/${ivy.local.default.artifact.pattern}" />
</filesystem>
</resolvers>
</ivyconf>
<ivyconf>
<resolvers>
<chain name="main" dual="true">
<resolver ref="shared"/>
<resolver ref="public"/>
</chain>
</resolvers>
</ivyconf>
<ivyconf>
<resolvers>
<chain name="default" returnFirst="true">
<resolver ref="local"/>
<resolver ref="main"/>
</chain>
</resolvers>
</ivyconf>
Here you are, you have enough clues to configure that the way you want... check the configuration documentation to see if what you want to do is possible, and go ahead !
I:\chained-resolvers\chainedresolvers-project>ant Buildfile: build.xml configure: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: resolve: :: resolving dependencies :: jayasoft/chained-resolvers-working@xmen confs: [default] downloading http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-2.0.jar(2.0) ... .................................... (165kB) [SUCCESSFUL ] apache/commons-lang-2.0/commons-lang.jar[jar] (5390ms) downloading file:/I:/chained-resolvers/config/repository/test-1.0.jar(1.0) ... . (1kB) [SUCCESSFUL ] jayasoft/test-1.0/test.jar[jar] (16ms) :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 2 | 2 | 0 | 0 || 2 | 2 | --------------------------------------------------------------------- :: retrieving :: jayasoft/chained-resolvers confs: [default] 2 artifacts copied, 0 already retrieved run: [mkdir] Created dir: I:\chained-resolvers\chainedresolvers-project\build [javac] Compiling 1 source file to I:\chained-resolvers\chainedresolvers-project\build [java] standard message :example world ! [java] capitalized by org.apache.commons.lang.WordUtils : Example World ! [java] upperCased by test.StringUtils : EXAMPLE WORLD ! BUILD SUCCESSFUL Total time: 9 seconds
I:\dual\project>ant Buildfile: build.xml configure: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: resolve: :: resolving dependencies :: jayasoft/hello-ivy-working@xmen confs: [default] downloading http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-2.0.jar(2.0) ... ..... ......... .......... ........... . (165kB) [SUCCESSFUL ] apache/commons-lang-2.0/commons-lang.jar[jar] (8032ms) downloading http://www.ibiblio.org/maven/commons-httpclient/jars/commons-httpclient-2.0.2.jar(2.0.2) ... ........... ...... .... .......... ............ ........ (220kB) [SUCCESSFUL ] apache/commons-httpclient-2.0.2/commons-httpclient.jar[jar] (10031ms) downloading http://www.ibiblio.org/maven/commons-logging/jars/commons-logging-1.0.4.jar(1.0.4) ... ......... (37kB) [SUCCESSFUL ] apache/commons-logging-1.0.4/commons-logging.jar[jar] (1469ms) :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 3 | 3 | 1 | 0 || 3 | 3 | --------------------------------------------------------------------- :: retrieving :: jayasoft/hello-ivy confs: [default] 3 artifacts copied, 0 already retrieved run: [mkdir] Created dir: I:\dual\project\build [javac] Compiling 1 source file to I:\dual\project\build [java] standard message : hello ivy ! [java] capitalized by org.apache.commons.lang.WordUtils : Hello Ivy ! [java] head status code with httpclient: 200 [java] now check if httpclient dependency on commons-logging has been realized [java] found logging class in classpath: interface org.apache.commons.logging.Log BUILD SUCCESSFUL Total time: 24 seconds
I:\standalone>ant publish Buildfile: build.xml configure: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: resolve: :: resolving dependencies :: jayasoft/standalone-working@xmen confs: [default] downloading http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-2.0.jar(2.0) ... .................................... (165kB) [SUCCESSFUL ] apache/commons-lang-2.0/commons-lang.jar[jar] (6672ms) :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 1 | 1 | 0 | 0 || 1 | 1 | --------------------------------------------------------------------- :: retrieving :: jayasoft/standalone confs: [default] 1 artifacts copied, 0 already retrieved compile: [mkdir] Created dir: I:\standalone\build\classes [javac] Compiling 1 source file to I:\standalone\build\classes jar: [propertyfile] Creating new property file: I:\standalone\build\classes\version.properties [jar] Building jar: I:\standalone\build\standalone.jar publish: :: delivering :: jayasoft/standalone-working@xmen :: 1 :: release :: Wed Apr 27 08:41:47 CEST 2005 delivering ivy file to I:\standalone/build/ivy.xml :: publishing :: jayasoft/standalone-working@xmen published standalone to I:\config\repository\standalone-1.jar published ivy to I:\config\repository\standalone-1.xml [echo] project standalone released with version 1 BUILD SUCCESSFUL Total time: 10 seconds
I:\depending>ant Buildfile: build.xml clean: configure: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: resolve: :: resolving dependencies :: jayasoft/depending-working@xmen confs: [default] [1] jayasoft/standalone downloading file:/I:/config/repository/standalone-1.jar(1) ... . (1kB) [SUCCESSFUL ] jayasoft/standalone-1/standalone.jar[jar] (15ms) :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 2 | 2 | 2 | 0 || 2 | 1 | --------------------------------------------------------------------- :: retrieving :: jayasoft/depending confs: [default] 2 artifacts copied, 0 already retrieved compile: [mkdir] Created dir: I:\depending\build\classes [javac] Compiling 1 source file to I:\depending\build\classes run: [java] you are using version 1 of class standalone.Main [java] standard message : i am depending.Main and standalone.Main will do the job for me [java] [standalone.Main] capitalizing string "i am depending.Main and standalone.Main will do the job for me" using org.apache.commons.lang.WordUtils [java] capitalized message : I Am Depending.main And Standalone.main Will Do The Job For Me BUILD SUCCESSFUL Total time: 3 seconds
I:\standalone>ant publish Buildfile: build.xml configure: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: resolve: :: resolving dependencies :: jayasoft/standalone-working@xmen confs: [default] :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 1 | 0 | 0 | 0 || 1 | 0 | --------------------------------------------------------------------- :: retrieving :: jayasoft/standalone confs: [default] 0 artifacts copied, 1 already retrieved compile: jar: [propertyfile] Updating property file: I:\standalone\build\classes\version.properties [jar] Building jar: I:\standalone\build\standalone.jar publish: [delete] Deleting: I:\standalone\build\ivy.xml :: delivering :: jayasoft/standalone-working@xmen :: 2 :: release :: Wed Apr 27 09:17:13 CEST 2005 delivering ivy file to I:\standalone/build/ivy.xml :: publishing :: jayasoft/standalone-working@xmen published standalone to I:\config\repository\standalone-2.jar published ivy to I:\config\repository\standalone-2.xml [echo] project standalone released with version 2 BUILD SUCCESSFUL Total time: 2 seconds
I:\dependence\standalone>dir ..\config\repository /w Le volume dans le lecteur I s'appelle DATA Le numéro de série du volume est 30E5-91BA Répertoire de I:\dependence\config\repository [.] [..] standalone-1.jar standalone-1.xml standalone-2.jar standalone-2.xml 4 fichier(s) 3 936 octets 2 Rép(s) 9 874 350 080 octets libres I:\dependence\standalone>
I:\depending>ant Buildfile: build.xml clean: [delete] Deleting 3 files from I:\depending [delete] Deleted 4 directories from I:\depending configure: :: Ivy 1.0-rc3 - 20050421161206 :: http://ivy.jayasoft.org/ :: resolve: :: resolving dependencies :: jayasoft/depending-working@xmen confs: [default] [2] jayasoft/standalone downloading file:/I:/config/repository/standalone-2.jar(2) ... . (1kB) [SUCCESSFUL ] jayasoft/standalone-2/standalone.jar[jar] (0ms) :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 2 | 2 | 2 | 0 || 2 | 1 | --------------------------------------------------------------------- :: retrieving :: jayasoft/depending confs: [default] 2 artifacts copied, 0 already retrieved compile: [mkdir] Created dir: I:\depending\build\classes [javac] Compiling 1 source file to I:\depending\build\classes run: [java] you are using version 2 of class standalone.Main [java] standard message : i am depending.Main and standalone.Main will do the job for me [java] [standalone.Main] capitalizing string "i am depending.Main and standalone.Main will do the job for me" using org.apache.commons.lang.WordUtils [java] capitalized message : I Am Depending.main And Standalone.main Will Do The Job For Me BUILD SUCCESSFUL Total time: 3 seconds
Warning: tutorial in progress !
In the previous tutorial you have seen how to deal with dependencies between two simple projects.
This tutorial will guide you through the use of ivy in a more complete environment. All the sources of this tutorial are available in src/example/multi-project in ivy distribution (warning: the sources attached with ivy 1.3 contain an error in the common.xml file. Please use either latest build to find proper example sources or replace the common.xml file with this one).
Here is a 10000ft overview of the projects involved in this tutorial:
For sure this is not aimed to demonstrate how to develop a complex app or give indication of advanced algorithm :-)
But this gives a simple understanding of how ivy can be used to develop an application divided in multitple modules.
Now, here is how these modules relate to each other:
Modules in yellow are the modules described in this tutorial, and modules in blue are external dependencies (we will see how to generate this graph later in this tutorial).
As you can see, we have here a pretty interesting set of modules with dependencies between each other, each depending on the latest version of the others.
The sources for this tutorial can be found in src/example/multi-project in the ivy distribution. In this directory, you will find the following files:
contains a directory per module, with for each
<ivy-module version="1.0">
<info
organisation="jayasoft"
module="find"
status="integration"/>
<configurations>
<conf name="core"/>
<conf name="standalone" extends="core"/>
</configurations>
<publications>
<artifact name="find" type="jar" conf="core" />
</publications>
<dependencies>
<dependency name="version" rev="latest.integration" conf="core->default" />
<dependency name="list" rev="latest.integration" conf="core" />
<dependency org="apache" name="commons-collections" rev="3.1" conf="core->default" />
<dependency org="apache" name="commons-cli" rev="1.0" conf="standalone->default" />
</dependencies>
</ivy-module>
<project name="find" default="compile">
<property file="build.properties"/>
<import file="${common.dir}/common.xml"/>
</project>
projects.dir = ${basedir}/..
wkspace.dir = ${projects.dir}/..
common.dir = ${wkspace.dir}/common
Note that this doesn't demonstrate good practice for software development in general, in particular you won't find any unit test in this samples, even if we think unit testing is very important. But this isn't the aim of this tutorial.
Now that you are a bit more familiar with the structure, let's have a look at the most important part of this example: the common build file. Indeed, as you have seen all modules build files only import the common build file, and defines their dependencies in their ivy files (with which you should begin to be familiar).
So, here are some aspects of this common build file:
<target name="configure">
<!-- setup ivy default configuration with some custom info -->
<property name="ivy.local.default.root" value="${repository.dir}/local"/>
<property name="ivy.shared.default.root" value="${repository.dir}/shared"/>
<!-- here is how we would have configured ivy if we had our own ivyconf file
<ivy:configure file="${common.dir}/ivyconf.xml" />
-->
</target>
This target configures ivy only by setting two properties: the location for the local repository and the location for the shared repository. It's the only configuration done here, since ivy 1.3 is configured by default to work in a team environment (see default configuration tutorial for details about this). For sure in a real environment the shared repository location would rather be in a team shared directory (or in a more complex repository, again see the default configuration tutorial to see how to use something really different).
This target only indicates in comments how the configuration would have been done if the default configuration wasn't ok for our purpose.
<target name="resolve" depends="configure, clean-lib" description="--> retrieve dependencies with ivy">
<mkdir dir="${lib.dir}"/> <!-- not usually necessary, ivy creates the directory IF there are dependencies -->
<!-- this target is named resolve even if we do a retrieve:
in fact a resolve will be called, and then the retrieve will simply copy files in the lib directory -->
<ivy:retrieve pattern="${lib.dir}/[artifact].[ext]" />
</target>
<target name="publish" depends="clean-build, new-version, jar" description="--> publish this project in the ivy repository">
<property name="revision" value="${version}"/>
<ivy:publish artifactspattern="${build.dir}/[artifact].[ext]"
resolver="shared"
pubrevision="${revision}"
status="release"
/>
<echo message="project ${ant.project.name} released with version ${revision}" />
</target>
<target name="publish-local" depends="local-version, jar" description="--> publish this project in the local ivy repository">
<delete file="${build.dir}/ivy.xml"/> <!-- delete last produced ivy file to be sure a new one will be generated -->
<ivy:publish artifactspattern="${build.dir}/[artifact].[ext]"
resolver="local"
pubrevision="${revision}"
pubdate="${now}"
status="integration"
/>
<echo message="project ${ant.project.name} published locally with version ${revision}" />
</target>
<target name="clean-local" depends="configure" description="cleans the local repository for the current module">
<delete dir="${ivy.local.default.root}/${ant.project.name}"/>
</target>
<target name="report" depends="resolve" description="--> generates a report of dependencies">
<ivy:report todir="${build.dir}"/>
</target>
For example, to generate a graph like the one shown at the beginning of this tutorial, you just have to follow the instructions given here with the graphml file you will find in projects/console/build/
after having called report in the console project, and that's it, you have a clear overview of all your app dependencies !
This tutorial introduces the use of configuration in ivy files. Ivy configurations is indeed a very important concept. Someone even told me one day that using Ivy without using configurations is like eating a good cheese without touching the glass of Chateau Margaux 1976 you have just aside :-)
More seriously, configurations in ivy can be better understood as views on your module, and you will see how they can be used efficiently here.
Reference documentation on configurations can be find here and here.
Source code available in src/example/configurations/multi-projects.
We have two projects :
- a library that define an api to filter String array and two implementations of this api.
- a very small app that use this library.
The library produces 3 artifacts:
- the api jar,
- an implementation jar with no external dependency,
- an other implementation that needs commons-collection to perform.
The application only need api to compile and can use any of the two implementation at runtime.
The first project we defined in this tutorial is the filter-framework.
In order to have a fine grained artifacts publication definition, we defined configurations to map usage other can make of our library.
<ivy-module version="1.3">
<info organisation="jayasoft" module="filter-framework"/>
<configurations>
<conf name="api" description="only provide filter framework API"/>
<conf name="homemade-impl" extends="api" description="provide a home made implementation of our api"/>
<conf name="cc-impl" extends="api" description="provide an implementation that use apache common collection framework"/>
<conf name="test" extends="cc-impl" visibility="private" description="for testing our framework"/>
</configurations>
<publications>
<artifact name="filter-api" type="jar" conf="api" ext="jar"/>
<artifact name="filter-hmimpl" type="jar" conf="homemade-impl" ext="jar"/>
<artifact name="filter-ccimpl" type="jar" conf="cc-impl" ext="jar"/>
</publications>
<dependencies>
<dependency org="apache" name="commons-collections" rev="3.1" conf="cc-impl->default"/>
<dependency org="junit" name="junit" rev="3.8" conf="test->default"/>
</dependencies>
</ivy-module>
As you can see we defined 3 public configurations and a private one (defined junit dependency for testing).
The 2 implementations conf homemade-impl, cc-impl extends api configuration so artifacts defined in api will also be required in its extending conf.
In the publications tag we defined the artifacts we produce (here it's jars) and we affect them a configuration.
Later when others will use our library they will have a very flexible way to defined what they need.
The library project is build using ant. Open a shell in the root directory of the project and type ant.
Buildfile: build.xml clean: resolve: :: Ivy 20060123130642 - 20060123130642 :: http://ivy.jayasoft.org/ :: no configuration file found, using default... :: configuring :: url = jar:file:/C:/dev/ant/apache-ant-1.6.2/lib/ivy-20060123130642.jar!/fr/jayasoft/ivy/conf/ivyconf.xml :: resolving dependencies :: [ jayasoft | filter-framework | working@SPIDER ] confs: [api, homemade-impl, cc-impl, test] found [ apache | commons-collections | 3.1 ] in main found [ junit | junit | 3.8 ] in main downloading http://www.ibiblio.org/maven/commons-collections/jars/commons-collections-3.1.jar ................(546kB) [SUCCESSFUL ] [ apache | commons-collections | 3.1 ]/commons-collections.jar[jar] (34320ms) downloading http://www.ibiblio.org/maven/junit/jars/junit-3.8.jar ........................... (118kB) [SUCCESSFUL ] [ junit | junit | 3.8 ]/junit.jar[jar] (8462ms) :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | api | 0 | 0 | 0 | 0 || 0 | 0 | | homemade-impl | 0 | 0 | 0 | 0 || 0 | 0 | | cc-impl | 1 | 1 | 1 | 0 || 1 | 1 | | test | 2 | 2 | 1 | 0 || 2 | 2 | --------------------------------------------------------------------- :: retrieving :: [ jayasoft | filter-framework ] confs: [api, homemade-impl, cc-impl, test] 3 artifacts copied, 0 already retrieved build: [mkdir] Created dir: D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\build [mkdir] Created dir: D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\distrib [javac] Compiling 4 source files to D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\build [jar] Building jar: D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\distrib\filter-api.jar [jar] Building jar: D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\distrib\filter-hmimpl.jar [jar] Building jar: D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\distrib\filter-ccimpl.jar test: [mkdir] Created dir: D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\build\test-report [mkdir] Created dir: D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\build\test-classes [javac] Compiling 3 source files to D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\filter-framework\build\test-classes [junit] Running filter.ccimpl.CCFilterTest [junit] Tests run: 5, Failures: 0, Errors: 0, Time elapsed: 0.02 sec [junit] Running filter.hmimpl.HMFilterTest [junit] Tests run: 5, Failures: 0, Errors: 0, Time elapsed: 0.01 sec publish: :: delivering :: [ jayasoft | filter-framework | working@SPIDER ] :: 1.3 :: release :: Tue Jan 24 10:53:41 CET 2006 delivering ivy file to distrib/ivy.xml :: publishing :: [ jayasoft | filter-framework | working@SPIDER ] published filter-api to D:\users\mm\.ivy/local/jayasoft/filter-framework/1.3/jars/filter-api.jar published filter-ccimpl to D:\users\mm\.ivy/local/jayasoft/filter-framework/1.3/jars/filter-ccimpl.jar published filter-hmimpl to D:\users\mm\.ivy/local/jayasoft/filter-framework/1.3/jars/filter-hmimpl.jar published ivy to D:\users\mm\.ivy/local/jayasoft/filter-framework/1.3/ivys/ivy.xml [echo] project filter-framework released with version 1.3 BUILD SUCCESSFUL
The ant's default target is publish.
This target use ivy to publish our library binaries in a local repository.
As we do not specify any repository path the default one is use. ({home.dir}/.ivy/local/jayasoft/filter-framework/)
Now we are ready to use our library.
Now that we have shipped our fantastic library, we want to use it!
The tutorial comes with a sample application called myapp. You will find it in the tutorial folder.
<ivy-module version="1.3">
<info organisation="jayasoft" module="myapp"/>
<configurations>
<conf name="build" visibility="private" description="compilation only need api jar" />
<conf name="noexternaljar" description="use only company jar" />
<conf name="withexternaljar" description="use company jar and third party jars" />
</configurations>
<dependencies>
<dependency org="jayasoft" name="filter-framework" rev="latest.integration" conf="build->api; noexternaljar->homemade-impl; withexternaljar->cc-impl"/>
</dependencies>
</ivy-module>
We create 3 configurations that define the way we want to use the application.
The build configuration, (as said before) only need api to compile.
The other configuration are defined for runtime.
One configuration will only use "home-made" jars, and the second one will use external jars.
We also defined a dependency on the previous library.
In the dependency we use configuration mapping to match ours and library configurations.
You can found more information on configuration mapping here
Note that we never declares any of the dependency artifacts we need in each configuration: it's the dependency module file which declares the published artifacts and which should be used in each configuration.
In the ant buld.xml file we defined a resolve target as follow:
<target name="resolve" description="--> retreive dependencies with ivy">
<ivy:retrieve pattern="${ivy.lib.dir}/[conf]/[artifact].[ext]"/>
</target>
When we call this target, Ivy will do a resolve using our ivy.xml file in the root folder and will after do retrieve putting all the artifacts in folder for each configuration. Here is how your lib directory should look like after a call to this target:
Répertoire de D:\ivy\src\example\configurations\multi-projects\myapp\lib 01/24/2006 11:19 AMbuild 01/24/2006 11:19 AM noexternaljar 01/24/2006 11:19 AM withexternaljar 0 fichier(s) 0 octets Répertoire de D:\ivy\src\example\configurations\multi-projects\myapp\lib\build 01/24/2006 10:53 AM 1,174 filter-api.jar 1 fichier(s) 1,174 octets Répertoire de D:\ivy\src\example\configurations\multi-projects\myapp\lib\noexternaljar 01/24/2006 10:53 AM 1,174 filter-api.jar 01/24/2006 10:53 AM 1,030 filter-hmimpl.jar 2 fichier(s) 2,204 octets Répertoire de D:\ivy\src\example\configurations\multi-projects\myapp\lib\withexternaljar 01/24/2006 10:53 AM 559,366 commons-collections.jar 01/24/2006 10:53 AM 1,174 filter-api.jar 01/24/2006 10:53 AM 1,626 filter-ccimpl.jar 3 fichier(s) 562,166 octets
Let's try to launch our app.
Use ant to run the application.
Default ant target is run-cc and will launch application using common collection jar.
Buildfile: build.xml resolve: :: Ivy 20060123130642 - 20060123130642 :: http://ivy.jayasoft.org/ :: no configuration file found, using default... :: configuring :: url = jar:file:/C:/dev/ant/apache-ant-1.6.2/lib/ivy-20060123130642.jar!/fr/jayasoft/ivy/conf/ivyconf.xml :: resolving dependencies :: [ jayasoft | myapp | working@SPIDER ] confs: [build, noexternaljar, withexternaljar] found [ jayasoft | filter-framework | 1.3 ] in local [1.3] [ jayasoft | filter-framework | latest.integration ] found [ apache | commons-collections | 3.1 ] in default downloading D:\users\mm\.ivy\local\jayasoft\filter-framework\1.3\jars\filter-ccimpl.jar .... (1kB) [SUCCESSFUL ] [ jayasoft | filter-framework | 1.3 ]/filter-ccimpl.jar[jar] (0ms) downloading D:\users\mm\.ivy\local\jayasoft\filter-framework\1.3\jars\filter-api.jar .... (1kB) [SUCCESSFUL ] [ jayasoft | filter-framework | 1.3 ]/filter-api.jar[jar] (0ms) downloading D:\users\mm\.ivy\local\jayasoft\filter-framework\1.3\jars\filter-hmimpl.jar .... (1kB) [SUCCESSFUL ] [ jayasoft | filter-framework | 1.3 ]/filter-hmimpl.jar[jar] (10ms) :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | build | 1 | 1 | 1 | 0 || 1 | 1 | | noexternaljar | 1 | 1 | 1 | 0 || 2 | 2 | | withexternaljar | 2 | 1 | 1 | 0 || 3 | 2 | --------------------------------------------------------------------- :: retrieving :: [ jayasoft | myapp ] confs: [build, noexternaljar, withexternaljar] 6 artifacts copied, 0 already retrieved build: [mkdir] Created dir: D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\myapp\build [javac] Compiling 1 source file to D:\svn\jayasoft\projects\tools\ivy\src\example\configurations\multi-projects\myapp\build run-cc: [java] Filtering with:class filter.ccimpl.CCFilter [java] Result :[two, tree]
Launching application with only home made jars is straingforward.
type ant run-hm
Buildfile: build.xml resolve: :: Ivy 20060123130642 - 20060123130642 :: http://ivy.jayasoft.org/ :: no configuration file found, using default... :: configuring :: url = jar:file:/C:/dev/ant/apache-ant-1.6.2/lib/ivy-20060123130642.jar!/fr/jayasoft/ivy/conf/ivyconf.xml :: resolving dependencies :: [ jayasoft | myapp | working@SPIDER ] confs: [build, noexternaljar, withexternaljar] found [ jayasoft | filter-framework | 1.3 ] in default [1.3] [ jayasoft | filter-framework | latest.integration ] found [ apache | commons-collections | 3.1 ] in default :: resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | build | 1 | 1 | 0 | 0 || 1 | 0 | | noexternaljar | 1 | 1 | 0 | 0 || 2 | 0 | | withexternaljar | 2 | 1 | 0 | 0 || 3 | 0 | --------------------------------------------------------------------- :: retrieving :: [ jayasoft | myapp ] confs: [build, noexternaljar, withexternaljar] 0 artifacts copied, 6 already retrieved build: run-hm: [java] Filtering with:class filter.hmimpl.HMFilter [java] Result :[two, tree] BUILD SUCCESSFUL
You should use configuration as often as possible
Configurations are very important concept in ivy. They allow you to groups artifacts set by meaning.
When you write ivy file for projects that are supposed to be reused, use configurations to allow people to get only they what they need without having to specify it by hand using artifact tag in dependency section.
With the install ant task you are given the possibility to copy ivy descriptors and artifacts found from a resolver and publish them into another resolver.
This tutorial will show you how to build your own clean enterprise repository of ivy descriptors and modules artifacts.
We will first use some basic ivy configuration files to show how it works, and then we will use advanced features like namespaces to build a real enterprise repository.
The project that we will use is quite simple.
It is compouned of an ant build file, and some ivy conf files.
Here are the accessible target that we will use :
Z:\ivy-repository>ant -p Buildfile: build.xml Main targets: advanced --> retrieve files from public repositories (ivyrep, ibiblio, ...) using namespaces basic --> retrieve files from well formatted ivy repositories basic-deps --> retrieve files from well formatted ivy repositories with dependencies clean-cache --> clean the cache clean-repo --> clean the destination repository commons-lang-1-0-ibiblio-no-namespace --> retrieve commons-lang 1.0 from ibiblio maven using no namespaces commons-lang-1-0-ibiblio-with-namespace --> retrieve commons-lang 1.0 from ibiblio maven using namespaces maven1 --> retrieve commons-lang 1.0 from maven1 repo using namespaces maven2 --> retrieve files from maven2 repo using namespaces Default target: basic
!!!! UNDER CONSTRUCTION !!!!
We will study here two cases, corresponding to the two basics targets found in the previous build.xml project file.
The ivy conf file that we will use is very simple here. It defines two resolvers, libraries and local-repository. The first one is used to retrieve the files that we want, the second is used to copy them. The second one will become our own repository.
<ivyconf>
<conf defaultCache="${ivy.cache.dir}"
defaultResolver="local-repository"
defaultConflictManager="all" /> <!-- in order to get all revisions without any eviction -->
<resolvers>
<ivyrep name="libraries" />
<filesystem name="local-repository">
<ivy pattern="${dest.repo.dir}/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${dest.repo.dir}/[organisation]/[module]/[type]s/[artifact]-[revision].[type]"/>
</filesystem>
</resolvers>
</ivyconf>
Let's have a look at the basic target.
<target name="basic" depends="init-basic" description="--> retrieve files from well formatted ivy repositories">
<ivy:install organisation="apache" module="commons-lang" revision="1.0" from="${from-resolver}" to="${to-resolver}" />
</target>
Z:\ivy-repository>ant basic Buildfile: build.xml init-basic: :: Ivy 20060123130642 - 20060123130642 :: http://ivy.jayasoft.org/ :: :: configuring :: file = Z:\ivy-repository\ivy-conf-basic.xml basic: :: installing [ apache | commons-lang | 1.0 ] :: :: resolving dependencies :: found [ apache | commons-lang | 1.0 ] in libraries :: downloading artifacts to cache :: downloading http://www.ibiblio.org/maven/commons-lang/jars/commons-lang-1.0.jar ... ............ (62kB) [SUCCESSFUL ] [ apache | commons-lang | 1.0 ]/commons-lang.jar[jar] (1203ms) :: installing in local-repository :: published commons-lang to Z:\ivy-repository/ivy-local-repository/apache/commons-lang/jars/commons-lang-1.0.jar published ivy to Z:\ivy-repository/ivy-local-repository/apache/commons-lang/ivys/ivy-1.0.xml BUILD SUCCESSFUL Total time: 2 seconds
If we take a look at our repository :
Z:\ivy-repository>dir /s /B /A:-D ivy-local-repository Z:\ivy-repository\ivy-local-repository\apache\commons-lang\ivys\ivy-1.0.xml Z:\ivy-repository\ivy-local-repository\apache\commons-lang\jars\commons-lang-1.0.jar Z:\ivy-repository>
Now let's advance a little more by trying a module that has some dependencies. Here is the target that we will call :
<target name="basic-deps" depends="init-basic" description="--> retrieve files from well formatted ivy repositories with dependencies">
<ivy:install organisation="hibernate" module="hibernate" revision="2.1.8" from="${from-resolver}" to="${to-resolver}" transitive="true" />
</target>
Ok let's call the target :
Z:\ivy-repository>ant basic-deps Buildfile: build.xml init-basic: :: Ivy 20060123130642 - 20060123130642 :: http://ivy.jayasoft.org/ :: :: configuring :: file = Z:\ivy-repository\ivy-conf-basic.xml basic-deps: :: installing [ hibernate | hibernate | 2.1.8 ] :: :: resolving dependencies :: found [ hibernate | hibernate | 2.1.8 ] in libraries found [ cglib | cglib | 2.0.2 ] in libraries found [ apache | commons-collections | 2.1.1 ] in libraries found [ apache | commons-logging | 1.0.4 ] in libraries found [ dom4j | dom4j | 1.4 ] in libraries found [ ehcache | ehcache | 0.9 ] in libraries found [ odmg | odmg | 3.0 ] in libraries found [ sun | jta | 1.0 ] in libraries found [ apache | xalan | 2.4.0 ] in libraries found [ apache | xerces | 2.4.0 ] in libraries found [ sun | jdbc | 2.0 ] in libraries found [ sun | jca | 1.0 ] in libraries found [ sun | jaas | 1.0 ] in libraries found [ c3p0 | c3p0 | 0.8.4.5 ] in libraries found [ apache | commons-dbcp | 1.2.1 ] in libraries found [ apache | commons-pool | 1.2 ] in libraries found [ apache | commons-collections | 2.1 ] in libraries found [ apache | xerces | 2.0.2 ] in libraries found [ proxool | proxool | 0.8.3 ] in libraries found [ jboss | jboss-cache | 1.1.1 ] in libraries found [ opensymphony | oscache | 2.0 ] in libraries found [ apache | commons-logging | 1.0.3 ] in libraries found [ swarmcache | swarmcache | 1.0RC2 ] in libraries found [ apache | commons-logging | 1.0.2 ] in libraries found [ jgroups | jgroups | 2.2 ] in libraries :: downloading artifacts to cache :: downloading http://www.ibiblio.org/maven/hibernate/jars/hibernate-2.1.8.jar ... ........... ............ .. (944kB) [SUCCESSFUL ] [ hibernate | hibernate | 2.1.8 ]/hibernate.jar[jar] (97063ms) SOME MINUTES LATER .... ;-) downloading http://www.ibiblio.org/maven/commons-logging/jars/commons-logging-1.0.4.jar ... .. ...... .. (37kB) [SUCCESSFUL ] [ apache | commons-logging | 1.0.4 ]/commons-logging.jar[jar] (24172ms) BUILD SUCCESSFUL Total time: 14 minutes 57 seconds Z:\ivy-repository>
We can see here that ivy has resolved hibernate 2.1.8 and 24 depending modules. If we look at the ivy file for hibernate 2.1.8, we can see that it defines 17 dependencies. The 7 others that ivy retrieved, were transitive ones used in direct dependent modules of hibernate.
We can notice that we have retrieve 3 differents revisions of apache commons-logging (1.0.2, 1.0.3, 1.0.4) and 2 revisions of commons-collections (1.2, 1.2.1). This is due to the fact that we use the "no conflict" conflic manager in the ivyconf file.
We do not want to evict any modules because we are building our own repository !
8 modules artifacts have not been downloaded cause they have not been found on ibiblio with the ivyconf as it is.
We will see how to handle this problem in the advanced tutorial.
If we look at our repository now, it starts to look to something good :
Z:\ivy-repository>dir /s /B /A:-D ivy-local-repository Z:\ivy-repository\ivy-local-repository\apache\commons-collections\ivys\ivy-2.1.1.xml Z:\ivy-repository\ivy-local-repository\apache\commons-collections\ivys\ivy-2.1.xml Z:\ivy-repository\ivy-local-repository\apache\commons-collections\jars\commons-collections-2.1.1.jar Z:\ivy-repository\ivy-local-repository\apache\commons-collections\jars\commons-collections-2.1.jar Z:\ivy-repository\ivy-local-repository\apache\commons-dbcp\ivys\ivy-1.2.1.xml Z:\ivy-repository\ivy-local-repository\apache\commons-dbcp\jars\commons-dbcp-1.2.1.jar Z:\ivy-repository\ivy-local-repository\apache\commons-lang\ivys\ivy-1.0.xml Z:\ivy-repository\ivy-local-repository\apache\commons-lang\jars\commons-lang-1.0.jar Z:\ivy-repository\ivy-local-repository\apache\commons-logging\ivys\ivy-1.0.2.xml Z:\ivy-repository\ivy-local-repository\apache\commons-logging\ivys\ivy-1.0.3.xml Z:\ivy-repository\ivy-local-repository\apache\commons-logging\ivys\ivy-1.0.4.xml Z:\ivy-repository\ivy-local-repository\apache\commons-logging\jars\commons-logging-1.0.2.jar Z:\ivy-repository\ivy-local-repository\apache\commons-logging\jars\commons-logging-1.0.3.jar Z:\ivy-repository\ivy-local-repository\apache\commons-logging\jars\commons-logging-1.0.4.jar Z:\ivy-repository\ivy-local-repository\apache\commons-pool\ivys\ivy-1.2.xml Z:\ivy-repository\ivy-local-repository\apache\commons-pool\jars\commons-pool-1.2.jar Z:\ivy-repository\ivy-local-repository\apache\xalan\ivys\ivy-2.4.0.xml Z:\ivy-repository\ivy-local-repository\apache\xalan\jars\xalan-2.4.0.jar Z:\ivy-repository\ivy-local-repository\apache\xerces\ivys\ivy-2.0.2.xml Z:\ivy-repository\ivy-local-repository\apache\xerces\ivys\ivy-2.4.0.xml Z:\ivy-repository\ivy-local-repository\apache\xerces\jars\xerces-2.0.2.jar Z:\ivy-repository\ivy-local-repository\apache\xerces\jars\xerces-2.4.0.jar Z:\ivy-repository\ivy-local-repository\apache\xerces\jars\xmlParserAPIs-2.0.2.jar Z:\ivy-repository\ivy-local-repository\c3p0\c3p0\ivys\ivy-0.8.4.5.xml Z:\ivy-repository\ivy-local-repository\c3p0\c3p0\jars\c3p0-0.8.4.5.jar Z:\ivy-repository\ivy-local-repository\cglib\cglib\ivys\ivy-2.0.2.xml Z:\ivy-repository\ivy-local-repository\cglib\cglib\jars\cglib-full-2.0.2.jar Z:\ivy-repository\ivy-local-repository\dom4j\dom4j\ivys\ivy-1.4.xml Z:\ivy-repository\ivy-local-repository\dom4j\dom4j\jars\dom4j-1.4.jar Z:\ivy-repository\ivy-local-repository\ehcache\ehcache\ivys\ivy-0.9.xml Z:\ivy-repository\ivy-local-repository\ehcache\ehcache\jars\ehcache-0.9.jar Z:\ivy-repository\ivy-local-repository\hibernate\hibernate\ivys\ivy-2.1.8.xml Z:\ivy-repository\ivy-local-repository\hibernate\hibernate\jars\hibernate-2.1.8.jar Z:\ivy-repository\ivy-local-repository\jboss\jboss-cache\ivys\ivy-1.1.1.xml Z:\ivy-repository\ivy-local-repository\jgroups\jgroups\ivys\ivy-2.2.xml Z:\ivy-repository\ivy-local-repository\odmg\odmg\ivys\ivy-3.0.xml Z:\ivy-repository\ivy-local-repository\odmg\odmg\jars\odmg-3.0.jar Z:\ivy-repository\ivy-local-repository\opensymphony\oscache\ivys\ivy-2.0.xml Z:\ivy-repository\ivy-local-repository\proxool\proxool\ivys\ivy-0.8.3.xml Z:\ivy-repository\ivy-local-repository\proxool\proxool\jars\proxool-0.8.3.jar Z:\ivy-repository\ivy-local-repository\sun\jaas\ivys\ivy-1.0.xml Z:\ivy-repository\ivy-local-repository\sun\jca\ivys\ivy-1.0.xml Z:\ivy-repository\ivy-local-repository\sun\jdbc\ivys\ivy-2.0.xml Z:\ivy-repository\ivy-local-repository\sun\jta\ivys\ivy-1.0.xml Z:\ivy-repository\ivy-local-repository\swarmcache\swarmcache\ivys\ivy-1.0RC2.xml Z:\ivy-repository\ivy-local-repository\swarmcache\swarmcache\jars\swarmcache-1.0RC2.jar Z:\ivy-repository>
We will study in this section how to build a professionnal repository. What is a professionnal dependency resolver ? Our vision is to say that a good quality repository must follow clear rules about projects naming and must offer corrects, usuables, configurables and verified project descriptors. In order to achieve those goals, we think that you have to build your own repository.
We have seen in the previous example, that we could use some public repositories to begin to build our own repository.
Nevertheless, the result is not at all the one that was excepected. Indeed there is a problem with public repositories : their partial incompatibility.
For example, in ivyrep all commons-* projects belong to the apache organisation. In both ibiblio versions, it is not the case. The same problem could appear for other projects with other repositories, it is not the debate here.
To resolve some of the incompatibilities, we will use a new feature of ivy 1.3 the namespaces.
In order to use namespaces, we first need to see what's happening when none are used on repositories that do not fit our needs.
Let's take commons-lang 1.0 from ibiblio with a maven2 pom.
First clean your cache and repository.
Z:\ivy-repository>ant clean-cache clean-repo
Z:\ivy-repository>ant commons-lang-1-0-ibiblio-no-namespace Buildfile: build.xml init-advanced: :: Ivy 20060125070719 - 20060125070719 :: http://ivy.jayasoft.org/ :: :: configuring :: file = Z:\ivy-repository\ivy-conf-advanced.xml commons-lang-1-0-ibiblio-no-namespace: :: installing [ commons-lang | commons-lang | 1.0 ] :: :: resolving dependencies :: found [ commons-lang | commons-lang | 1.0 ] in ibiblio-maven2-nonamespace found [ junit | junit | 3.7 ] in ibiblio-maven2-nonamespace :: downloading artifacts to cache :: downloading http://www.ibiblio.org/maven2/commons-lang/commons-lang/1.0/commons-lang-1.0.jar ... .............. (62kB) [SUCCESSFUL ] [ commons-lang | commons-lang | 1.0 ]/commons-lang.jar[jar] (1313ms) downloading http://www.ibiblio.org/maven2/junit/junit/3.7/junit-3.7.jar ... ............. .............. (114kB) [SUCCESSFUL ] [ junit | junit | 3.7 ]/junit.jar[jar] (2360ms) :: installing in local-repository :: published commons-lang to Z:\ivy-repository/ivy-local-repository/commons-lang/commons-lang/jars/commons-lang-1.0.jar published ivy to Z:\ivy-repository/ivy-local-repository/commons-lang/commons-lang/ivys/ivy-1.0.xml published junit to Z:\ivy-repository/ivy-local-repository/junit/junit/jars/junit-3.7.jar published ivy to Z:\ivy-repository/ivy-local-repository/junit/junit/ivys/ivy-3.7.xml :: install resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 2 | 2 | 2 | 0 || 2 | 2 | --------------------------------------------------------------------- BUILD SUCCESSFUL Total time: 6 seconds Z:\ivy-repository>
Z:\ivy-repository>dir /s /B /A:-D ivy-local-repository Z:\ivy-repository\ivy-local-repository\commons-lang\commons-lang\ivys\ivy-1.0.xml Z:\ivy-repository\ivy-local-repository\commons-lang\commons-lang\jars\commons-lang-1.0.jar Z:\ivy-repository\ivy-local-repository\junit\junit\ivys\ivy-3.7.xml Z:\ivy-repository\ivy-local-repository\junit\junit\jars\junit-3.7.jar
<ivy-module version="1.0">
<info organisation="commons-lang"
module="commons-lang"
revision="1.0"
status="integration"
publication="20051124062021"
/>
Let's see directly the result, we will have some explanations after.
Clean your repo and cache, and call : ant commons-lang-1-0-ibiblio-with-namespace
Z:\ivy-repository>ant commons-lang-1-0-ibiblio-with-namespace Buildfile: build.xml init-advanced: :: Ivy non official version :: http://ivy.jayasoft.org/ :: :: configuring :: file = Z:\ivy-repository\ivy-conf-advanced.xml commons-lang-1-0-ibiblio-with-namespace: :: installing [ apache | commons-lang | 1.0 ] :: :: resolving dependencies :: found [ apache | commons-lang | 1.0 ] in ibiblio-maven2 found [ junit | junit | 3.7 ] in ibiblio-maven2 :: downloading artifacts to cache :: downloading http://www.ibiblio.org/maven2/commons-lang/commons-lang/1.0/commons-lang-1.0.jar ... ............. (62kB) [SUCCESSFUL ] [ apache | commons-lang | 1.0 ]/commons-lang.jar[jar] (1094ms) downloading http://www.ibiblio.org/maven2/junit/junit/3.7/junit-3.7.jar ... ............................ (114kB) [SUCCESSFUL ] [ junit | junit | 3.7 ]/junit.jar[jar] (1641ms) :: installing in local-repository :: published commons-lang to Z:\ivy-repository/ivy-local-repository/apache/commons-lang/jars/commons-lang-1.0.jar published ivy to Z:\ivy-repository/ivy-local-repository/apache/commons-lang/ivys/ivy-1.0.xml published junit to Z:\ivy-repository/ivy-local-repository/junit/junit/jars/junit-3.7.jar published ivy to Z:\ivy-repository/ivy-local-repository/junit/junit/ivys/ivy-3.7.xml :: install resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 2 | 2 | 2 | 0 || 2 | 2 | --------------------------------------------------------------------- BUILD SUCCESSFUL Total time: 5 seconds
Z:\ivy-repository>dir /s /B /A:-D ivy-local-repository Z:\ivy-repository\ivy-local-repository\apache\commons-lang\ivys\ivy-1.0.xml Z:\ivy-repository\ivy-local-repository\apache\commons-lang\jars\commons-lang-1.0.jar Z:\ivy-repository\ivy-local-repository\junit\junit\ivys\ivy-3.7.xml Z:\ivy-repository\ivy-local-repository\junit\junit\jars\junit-3.7.jar
<ivy-module version="1.0">
<info organisation="apache"
module="commons-lang"
revision="1.0"
status="integration"
publication="20051124062021"
/>
If we look at the ant target commons-lang-1-0-ibiblio-with-namespace, we can see that it uses a resolver called ibiblio-maven2.
Let's find it... The configuration file used for this test is ivy-conf-advanced.xml. This one includes ivy-maven2-ivyconf.xml where the required resolver is defined.
Let's see it's definition :
<ibiblio name="ibiblio-maven2"
root="${ibiblio-maven2-root}"
pattern="${ibiblio-maven2-pattern}"
m2compatible="true"
namespace="ibiblio-maven2"
/>
A namespace is defined by a set of rule, for ibiblio-maven2, whe have declared some rules :
<rule> <!-- imported apache maven1 projects -->
<fromsystem>
<src org="apache" module=".+"/>
<dest org="$m0" module="$m0"/>
</fromsystem>
<tosystem>
<src org="commons-.+" module="commons-.+" />
<src org="ant.*" module="ant.*" />
...
<src org="xmlrpc" module="xmlrpc" />
<dest org="apache" module="$m0"/>
</tosystem>
</rule>
<rule> <!-- new apache projects -->
<fromsystem>
<src org="apache" />
<dest org="org.apache"/>
</fromsystem>
<tosystem>
<src org="org.apache" />
<dest org="apache" />
</tosystem>
</rule>
Now that we have been well prepared, let's go to a real life example of building our repository.
We will now focus on a bigger example that uses different public repositories to retrieve the information.
In this tutorial we will use, in order of preference :
<resolvers>
<filesystem name="local-repository">
<ivy pattern="${dest.repo.dir}/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${dest.repo.dir}/[organisation]/[module]/[type]s/[artifact]-[revision].[type]"/>
</filesystem>
<chain name="libraries" returnFirst="false">
<resolver ref="local-repository" />
<ivyrep name="official-ivy-rep"/>
<resolver ref="ibiblio-maven2" />
</chain>
</resolvers>
What about to test our configuration with a big project : hibernate 3.0
Just run : ant advanced
Here we go !!!!!!!!
Z:\build-a-ivy-repository>ant advanced Buildfile: build.xml init-advanced: :: Ivy non official version :: http://ivy.jayasoft.org/ :: :: configuring :: file = Z:\build-a-ivy-repository\config\ivy-conf-advanced.xml advanced: :: installing [ hibernate | hibernate | 3.0 ] :: :: resolving dependencies :: found [ hibernate | hibernate | 3.0 ] in ibiblio-maven2 found [ apache | commons-logging | 1.0.4 ] in official-ivy-rep found [ apache | ant | 1.6.3 ] in ibiblio-maven2 found [ c3p0 | c3p0 | 0.8.4.5 ] in official-ivy-rep found [ proxool | proxool | 0.8.3 ] in official-ivy-rep found [ ehcache | ehcache | 1.1 ] in official-ivy-rep found [ apache | xerces | 2.5.0 ] in official-ivy-rep found [ apache | commons-collections | 2.1.1 ] in official-ivy-rep found [ opensymphony | oscache | 2.1 ] in ibiblio-maven2 found [ swarmcache | swarmcache | 1.0RC2 ] in official-ivy-rep found [ apache | commons-collections | 2.1 ] in official-ivy-rep found [ apache | commons-logging | 1.0.2 ] in official-ivy-rep found [ jgroups | jgroups | 2.2 ] in official-ivy-rep found [ jboss | jboss-cache | 1.2.2 ] in ibiblio-maven2 found [ jboss | jboss-system | 4.0.2 ] in ibiblio-maven2 found [ jboss | jboss-common | 4.0.2 ] in ibiblio-maven2 found [ jboss | jboss-minimal | 4.0.2 ] in ibiblio-maven2 found [ jboss | jboss-j2se | 200504122039 ] in ibiblio-maven2 found [ concurrent | concurrent | 1.3.4 ] in ibiblio-maven2 found [ jgroups | jgroups-all | 2.2.7 ] in ibiblio-maven2 found [ cglib | cglib | 2.0.2 ] in official-ivy-rep found [ objectweb | asm | 1.3.4 ] in official-ivy-rep found [ asm | asm | 1.4.3 ] in ibiblio-maven2 found [ javax.security | jacc | 1.0 ] in ibiblio-maven2 found [ dom4j | dom4j | 1.6 ] in ibiblio-maven2 found [ javax.transaction | jta | 1.0.1B ] in ibiblio-maven2 found [ hibernate | antlr | 2.7.5H3 ] in ibiblio-maven2 found [ odmg | odmg | 3.0 ] in official-ivy-rep :: downloading artifacts to cache :: downloading http://www.ibiblio.org/maven2/hibernate/hibernate/3.0/hibernate-3.0.jar ... .................................................. .. (1565kB) [SUCCESSFUL ] [ hibernate | hibernate | 3.0 ]/hibernate.jar[jar] (8500ms) downloading http://www.ibiblio.org/maven2/hibernate/antlr/2.7.5H3/antlr-2.7.5H3.jar ... SOME MINUTES LATER !!!!!!!!!! downloading http://www.ibiblio.org/maven/commons-logging/jars/commons-logging-1.0.4.jar ... ........ (37kB) [SUCCESSFUL ] [ apache | commons-logging | 1.0.4 ]/commons-logging.jar[jar] (1110ms) :: installing in local-repository :: published hibernate to Z:\build-a-ivy-repository/ivy-local-repository/hibernate/hibernate/jars/hibernate-3.0.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/hibernate/hibernate/ivys/ivy-3.0.xml published antlr to Z:\build-a-ivy-repository/ivy-local-repository/hibernate/antlr/jars/antlr-2.7.5H3.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/hibernate/antlr/ivys/ivy-2.7.5H3.xml published dom4j to Z:\build-a-ivy-repository/ivy-local-repository/dom4j/dom4j/jars/dom4j-1.6.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/dom4j/dom4j/ivys/ivy-1.6.xml missing artifact [ javax.security | jacc | 1.0 ]/jacc.jar[jar]: Z:\build-a-ivy-repository\cache\javax.security\jacc\jars\jacc-1.0.jar file does not exist published ivy to Z:\build-a-ivy-repository/ivy-local-repository/javax.security/jacc/ivys/ivy-1.0.xml published asm to Z:\build-a-ivy-repository/ivy-local-repository/asm/asm/jars/asm-1.4.3.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/asm/asm/ivys/ivy-1.4.3.xml published cglib-full to Z:\build-a-ivy-repository/ivy-local-repository/cglib/cglib/jars/cglib-full-2.0.2.jar published cglib to Z:\build-a-ivy-repository/ivy-local-repository/cglib/cglib/jars/cglib-2.0.2.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/cglib/cglib/ivys/ivy-2.0.2.xml published asm to Z:\build-a-ivy-repository/ivy-local-repository/objectweb/asm/jars/asm-1.3.4.jar published asm-util to Z:\build-a-ivy-repository/ivy-local-repository/objectweb/asm/jars/asm-util-1.3.4.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/objectweb/asm/ivys/ivy-1.3.4.xml published jboss-cache to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-cache/jars/jboss-cache-1.2.2.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-cache/ivys/ivy-1.2.2.xml published jgroups-all to Z:\build-a-ivy-repository/ivy-local-repository/jgroups/jgroups-all/jars/jgroups-all-2.2.7.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/jgroups/jgroups-all/ivys/ivy-2.2.7.xml published concurrent to Z:\build-a-ivy-repository/ivy-local-repository/concurrent/concurrent/jars/concurrent-1.3.4.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/concurrent/concurrent/ivys/ivy-1.3.4.xml published jboss-j2se to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-j2se/jars/jboss-j2se-200504122039.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-j2se/ivys/ivy-200504122039.xml published jboss-minimal to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-minimal/jars/jboss-minimal-4.0.2.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-minimal/ivys/ivy-4.0.2.xml published jboss-system to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-system/jars/jboss-system-4.0.2.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-system/ivys/ivy-4.0.2.xml published swarmcache to Z:\build-a-ivy-repository/ivy-local-repository/swarmcache/swarmcache/jars/swarmcache-1.0RC2.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/swarmcache/swarmcache/ivys/ivy-1.0RC2.xml missing artifact [ jgroups | jgroups | 2.2 ]/jgroups.jar[jar]: Z:\build-a-ivy-repository\cache\jgroups\jgroups\jars\jgroups-2.2.jar file does not exist published ivy to Z:\build-a-ivy-repository/ivy-local-repository/jgroups/jgroups/ivys/ivy-2.2.xml published commons-logging to Z:\build-a-ivy-repository/ivy-local-repository/apache/commons-logging/jars/commons-logging-1.0.2.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/apache/commons-logging/ivys/ivy-1.0.2.xml published oscache to Z:\build-a-ivy-repository/ivy-local-repository/opensymphony/oscache/jars/oscache-2.1.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/opensymphony/oscache/ivys/ivy-2.1.xml published c3p0 to Z:\build-a-ivy-repository/ivy-local-repository/c3p0/c3p0/jars/c3p0-0.8.4.5.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/c3p0/c3p0/ivys/ivy-0.8.4.5.xml published odmg to Z:\build-a-ivy-repository/ivy-local-repository/odmg/odmg/jars/odmg-3.0.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/odmg/odmg/ivys/ivy-3.0.xml published proxool to Z:\build-a-ivy-repository/ivy-local-repository/proxool/proxool/jars/proxool-0.8.3.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/proxool/proxool/ivys/ivy-0.8.3.xml missing artifact [ javax.transaction | jta | 1.0.1B ]/jta.jar[jar]: Z:\build-a-ivy-repository\cache\javax.transaction\jta\jars\jta-1.0.1B.jar file does not exist published ivy to Z:\build-a-ivy-repository/ivy-local-repository/javax.transaction/jta/ivys/ivy-1.0.1B.xml published jboss-common to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-common/jars/jboss-common-4.0.2.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/jboss/jboss-common/ivys/ivy-4.0.2.xml published ant to Z:\build-a-ivy-repository/ivy-local-repository/apache/ant/jars/ant-1.6.3.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/apache/ant/ivys/ivy-1.6.3.xml published commons-collections to Z:\build-a-ivy-repository/ivy-local-repository/apache/commons-collections/jars/commons-collections-2.1.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/apache/commons-collections/ivys/ivy-2.1.xml published ehcache to Z:\build-a-ivy-repository/ivy-local-repository/ehcache/ehcache/jars/ehcache-1.1.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/ehcache/ehcache/ivys/ivy-1.1.xml published commons-collections to Z:\build-a-ivy-repository/ivy-local-repository/apache/commons-collections/jars/commons-collections-2.1.1.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/apache/commons-collections/ivys/ivy-2.1.1.xml published xercesImpl to Z:\build-a-ivy-repository/ivy-local-repository/apache/xerces/jars/xercesImpl-2.5.0.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/apache/xerces/ivys/ivy-2.5.0.xml published commons-logging to Z:\build-a-ivy-repository/ivy-local-repository/apache/commons-logging/jars/commons-logging-1.0.4.jar published ivy to Z:\build-a-ivy-repository/ivy-local-repository/apache/commons-logging/ivys/ivy-1.0.4.xml :: install resolution report :: --------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 28 | 28 | 28 | 0 || 30 | 27 | --------------------------------------------------------------------- BUILD SUCCESSFUL Total time: 2 minutes 10 seconds Z:\build-a-ivy-repository>
OK, it seems that we have a good start point for our repository.
As you can see in the resolving part of the process :
:: resolving dependencies :: found [ hibernate | hibernate | 3.0 ] in ibiblio-maven2 found [ apache | commons-logging | 1.0.4 ] in official-ivy-rep ... found [ odmg | odmg | 3.0 ] in official-ivy-rep
Now what you need to do is to download missing artifacts, those not on ibiblio (from sun, ...) and correct the generated ivy files.
It is important to make a review of the generated ivy files because you could then benefit from all the power of ivy by defining for those projects good configurations and some other good things.
To ease finding generated files, just take a look at the generated resolve report in your cache. You will find there the projects for which a default ivy file was generated
Welcome to Ivy reference documentation.
If you don't know Ivy at all, give a glance at its features, the FAQ and the tutorials before digging into this reference documentation.
This documentation is decomposed in several parts:
This part gives you the meaning of some words used all over ivy doc, such as organisation, module, configurations, ...
This part introduces the main concepts used in Ivy: dependency resolvers, variables, patterns, and also a good introduction to a central ivy concept: module configurations.
As the title suggest, here you will have some explanations on how does ivy work internally, which can help to better understand and customize its use.
This part describe how to install Ivy
This part is dedicated to the specification of the configuration file of Ivy (usually called ivyconf.xml). It also gives the list of built-in dependency resolvers available in ivy.
This part is the reference of the specification of the ivy files, the files in which you describe your dependencies. If you have any question of what can be done or not in an ivy file, you will have the answer here.
This part describes how to use ivy: it briefly explains how to call ivy from command line, and deeply explains how to use it from ant, which is the main way to use ivy. It's in this section that all ant tasks brought by ivy are specified.
This part describes how to extend ivy, by writing your own dependency resolver, latest strategy, etc.
[artifact](-[revision]).[ext]
let you accept both myartifact-1.0.jar when a revision is set, and myartifact.jar (instead of myartifact-.jar) when no revision is setNow that you have been introduced to main ivy terminology and concepts, it is time to give some explanations about how ivy works.
Here are the steps followed by ivy to resolve your dependencies:
Ivy needs to be configured to be able to resolve your dependencies. This configuration is usually done with a configuration file, which defines a set of dependency resolvers. Each resolver is able to find ivy files and / or artifacts, given simple information such as organition, module, revision, artifact name, artifact type and artifact extension.
The configuration is also responsible for indicating which resolver should be used to resolve which module. This configuration is dependent only on your environment, i.e. where the modules and artifacts can be found.
A default configuration is used by ivy when none is given. This configuration uses ivyrep to resolve all modules.
The resolve time is the moment when ivy actually resolve the dependencies of one module. It first needs to access the ivy file of the module for which it resolves the dependencies.
Then, for each dependency declared in this file, it asks the appropriate resolver (according to configuration) to find the module (i.e. either an ivy file for it, or its artifacts if no ivy file can be found). It also uses a filesystem based cache to avoid asking for a dependency if it is already in cache (at least if possible, which is not the case with latest revisions).
If the resolver is a composite one (i.e. a chain or a dual resolver), several resolvers may actually be called to find the module.
When the dependency module has been found, its ivy file is downloaded to ivy cache. Then ivy checks if it has itself dependencies, in which case it recursilvely traverse the graph of dependencies.
All over this traversal, conflict management are done to prevent the access to a module as soon as possible.
When ivy has traversed the whole graph, it asks to the resolvers to download the artifacts corresponding to each dependencies which are not already in cache and which have not been evicted by conflict managers. All downloads are made to ivy cache.
Finally, an xml report is generated in cache, which allows ivy to easily know what are all the dependencies of the module, without traversing the graph again.
After this resolve step, two main steps are possible: either build a path with artifacts in cache, or copy them to another directory structure.
What is called retrieve in ivy is the fact to copy artifacts from the cache to another directory structure. This is done using a pattern, which indicates to ivy where the files should be copied.
For this, ivy uses the xml report in cache corresponding to the module it should retrieve to know which artifacts should be copied.
It also checks if the files are not already copied to maximize performances.
In some cases, it is preferable to use artifacts directly from the cache. Ivy is able to use the xml report generated at resolve time to build a path of all artifacts required.
This can be particularly useful especially when building plug-ins for IDE.
Finally, ivy is able to generate readable reports describing the dependencies resolution.
This is done with a simple xsl transformation of the xml report generated at resolve time.
<taskdef name="ivy-configure" classname="fr.jayasoft.ivy.ant.IvyConfigure"/> <taskdef name="ivy-resolve" classname="fr.jayasoft.ivy.ant.IvyResolve"/> <taskdef name="ivy-retrieve" classname="fr.jayasoft.ivy.ant.IvyRetrieve"/> <taskdef name="ivy-publish" classname="fr.jayasoft.ivy.ant.IvyPublish"/>- replace ivy:xxx tasks by ivy-xxx
ivyconf property properties conf include typedef latest-strategies parsers namespaces namespace rule fromsystem src dest tosystem src dest macrodef attribute any resolver resolvers any resolver conflict-managers modules module
Element | Description | Cardinality |
---|---|---|
property | set an ivy variable | 0..n |
properties | loads a properties file as ivy variables | 0..n |
conf | configures ivy with some defaults | 0..1 |
include | includes another ivyconf file | 0..n |
typedef | defines new types in ivy | 0..n |
latest-strategies | defines latest strategies | 0..1 |
parsers | defines module descriptor parsers | 0..1 |
namespaces | defines new namespaces | 0..1 |
macrodef | defines a new macro resolver | 0..n |
resolvers | defines dependency resolvers | 0..1 |
conflict-managers | defines conflicts managers | 0..1 |
modules | defines rules between modules and dependency resolvers | 0..1 |
Tag: property
Defines an ivy variable. since 1.3
The optional override attribute enables to avoid overriding the previous value of the varable, which makes the definition behave like ant properties, which is particularly useful to define default values (values which are used only if they haven't been defined yet).
Attribute | Description | Required |
---|---|---|
name | the name of the variable to define | Yes |
value | the new value the variable must take | Yes |
override | true if the previous value (if any) of the variable should overriden, false otherwise | No, defaults to true |
<property name="myvar" value="myvalue"/>
<property name="myvar" value="myvalue" override="false"/>
Attribute | Description | Required |
---|---|---|
file | a path to a properties file to load | Yes |
override | indicates if the variable found in the properties file should override their previous value, if any since 1.3 | No, defaults to true |
Attribute | Description | Required |
---|---|---|
defaultCache | a path to a directory to use as default cache | No, defaults to .ivy-cache in user home |
defaultResolver | the name of the default resolver to use | No, but all modules should be configured in the modules section if not provided |
defaultLatestStrategy | the name of the default latest strategy to use | No, defaults to latest-revision |
defaultConflictManager | the name of the default conflict manager to use | No, defaults to latest-revision |
validate | Indicates if ivy files should be validated against ivy.xsd or not. | No, defaults to true |
checkUpToDate | Indicates if date should be checked before retrieving artifacts from cache | No, defaults to true |
cacheIvyPattern | a pattern to indicate where ivy files should be put in cache | No, defaults to [organisation]/[module]/ivy-[revision].xml |
cacheArtifactPattern | a pattern to indicate where artifact files should be put in cache | No, defaults to [organisation]/[module]/[type]s/[artifact]-[revision].[ext] |
useRemoteConfig | true to configure ivyrep and ibiblio resolver from a remote configuration file (updated with changes in those repository structure if any) (since 1.2) | No, defaults to false |
Tag: include
Includes another ivyconf file as if it were part of this one. since 1.3
The included ivyconf file has to be a complete well formed ivyconf file, i.e. it does have to include the <ivyconf>
tag.
Attribute | Description | Required |
---|---|---|
file | a path to the ivyconf file to include | Yes |
<ivyconf>
<property name="myrepository" value="path/to/my/real/rep"/>
<conf defaultResolver="default"/>
<include file="path/to/ivyconf-default.xml"/>
</ivyconf>
<ivyconf>
<property name="myrepository" value="path/to/rep" overwrite="false"/>
<resolvers>
<ivyrep name="default" ivyroot="${myrepository}"/>
</resolvers>
</ivyconf>
The included ivyconf defines a resolver named default, which is an ivyrep resolver, with its root configured as being the value of myrepository variable. This variable is given the value path/to/rep in the included file, but because the attribute overwrite is set to false, it will not overide the value given in the main ivyconf including this one, so the value used for myrepository will be path/to/my/real/rep.
<ivyconf>
<include file="ivyconf-macro.xml"/>
<resolvers>
<mymacro name="includeworks" mymainrep="included/myrep" mysecondrep="included/secondrep"/>
</resolvers>
</ivyconf>
Attribute | Description | Required |
---|---|---|
name | the name of the type to define. This name is then used as an xml tag. | Yes |
classname | the fully qualified class name of the type to define. | Yes |
Element | Description | Cardinality |
---|---|---|
any latest strategy | adds a latest strategy to the list of available strategies | 0..n |
Tag: parsers
Defines a list of module descriptor parsers usable in ivy. Each parser defines which resources (which descriptor file) it accepts.
The child tag used for the parser must be equal to a name of a parser type (added with the typedef tag).
Note that when looking for a parser, ivy queries the parsers list in the reverse order. So the last parser in the list will be queried first. Consequently, if the last parser accepts all resources, the other parsers will never have a chance to parse the resource.
Two parsers are available by default and thus do not need to be declared in this section:
Element | Description | Cardinality |
---|---|---|
any module descriptor parser | adds a module descriptor parser to the list of available parsers | 0..n |
Tag: namespaces
Namespaces are an advanced feature of Ivy which let you use resolvers in which module names and organisations are not consistent between each other.
For instance, if you want to use maven2 repository and ivyrep collectively, you will face some naming issues. For example all apache commons projects are declared to be part of the organisation apache in ivyrep whereas in maven2 ibiblio repository, they are declared to be part of the organisation of the same name of the module.
So if you try to use both maven2 and ivyrep repositories, you will face some issues like:
How do I declare a dependency on commons-lang ?
I have an error while trying to resolve module xxx. It says that it depends on [commons-httpclient commons-httpclient] ant that it isn't available.
...
Ivy has an answer to give to this kind of troubles, and this answer is called namespaces. In short, you can affect a namespace to each dependency resolver in Ivy, and each namespace defines rules to convert names from the system namespace to the defined namespace itself, and vice versa.
This very powerful feature is thoroughly used in the build your own repository tutorial, and this is a good place to have examples of what can be done with namespaces.
Element | Description | Cardinality |
---|---|---|
namespace | defines a new namespace | 0..n |
Tag: namespace
Defines a new namespace. A namespace is identified by a name, which is used to reference the namespace in the resolvers using the namespace.
Namespaces overview is given in the namespaces documentation.
A namespace mainly consists of a list of rules, each rule defining a translation between system namespace and the defined namespace, and vice versa.
There are two main possibilities for using these rules. By default, a namespace iterate through the rules, and when it finds one that translate the given name, it returns the translated name. But the namespace can be configured to do use the list as a translator chain: in this case, all rules are applied in order, the result of the first rule translation being passed to the second, and so on.
Attribute | Description | Required |
---|---|---|
name | the namespace name | Yes |
chainrules | true to indicate that namespaces rules should be chained, false otherwise | No, defaults to false |
Element | Description | Cardinality |
---|---|---|
rule | defines a new namespace rule | 0..n |
<namespace name="test">
<rule>
<fromsystem>
<src org="systemorg"/>
<dest org="A"/>
</fromsystem>
<tosystem>
<src org="A"/>
<dest org="systemorg"/>
</tosystem>
</rule>
</namespace>
<namespace name="test">
<rule>
<fromsystem>
<src org="systemorg2" module="system\-(.+)"/>
<dest org="B" module="$m1"/>
</fromsystem>
<tosystem>
<src org="B" module=".+"/>
<dest org="systemorg2" module="system-$m0"/>
</tosystem>
</rule>
</namespace>
<namespace name="test" chainrules="true">
<rule>
<fromsystem>
<src org="systemorg"/>
<dest org="A"/>
</fromsystem>
<tosystem>
<src org="A"/>
<dest org="systemorg"/>
</tosystem>
</rule>
<rule>
<fromsystem>
<src module="systemmod"/>
<dest module="A"/>
</fromsystem>
<tosystem>
<src module="A"/>
<dest module="systemmod"/>
</tosystem>
</rule>
<rule>
<fromsystem>
<src module="systemmod2"/>
<dest module="B"/>
</fromsystem>
<tosystem>
<src module="B"/>
<dest module="systemmod2"/>
</tosystem>
</rule>
</namespace>
Tag: rule
Defines a new namespace rule. A rule defines a translation between system namespace and the defined namespace, and vice versa.
See namespace doc for details.
Element | Description | Cardinality |
---|---|---|
fromsystem | defines the translation to apply from system namespace to the defined namespace | 1 |
tosystem | defines the translation to apply from the defined namespace to system namespace | 1 |
Tag: fromsystem / tosystem
Defines a one way translation rule, i.e. a translation from system namespace to the defined namespace or vice versa.
Element | Description | Cardinality |
---|---|---|
src | defines a source name which can be accepted | 1..n |
dest | defines the translation to apply when a name is accepted by an src pattern | 1 |
Tag: src
Defines the acceptation part of a translation rule. If a name matches this src, it will be translated using the dest part.
Attribute | Description | Required |
---|---|---|
org | the organisation to match as a regexp | No, defaults to .* |
module | the module name to match as a regexp | No, defaults to .* |
rev | the revision to match as a regexp | No, defaults to .* |
Tag: dest
Defines the translation part of a translation rule. If a name has matched a corresponding src, it will be translated using this dest part.
The new names can contain references to groups of the matched name, using a slightly modified regexp syntax. Indeed, referenced groups can be part of either the organisation, module or revision part of the original name. So, to reference the groups, you just have to add a letter identifying the part in which the group should be selected: o for organisation, m for module, and r for revision.
For instance, $o0 matches the whole matched organisation, and $m0 the whole matched module name. $o1 matches the first group of the matched organisation.
For details about regexp and groups, see the Pattern class documentation in the jdk.
Attribute | Description | Required |
---|---|---|
org | the new organisation name | No, defaults to $o0 |
module | the new module name | No, defaults to $m0 |
rev | the new revision | No, defaults to $r0 |
<fromsystem>
<src org="systemorg2" module="system\-(.+)"/>
<dest org="B" module="$m1"/>
</fromsystem>
system-
of the original name.
Tag: macrodef
Defines a new dependency resolver type based upon an other one. This definition is very similar to the macrodef feature of ant for defining macro tasks. since 1.3
This task eases the lot the process of creating new dependency resolver, because it avoid writing java code.
It is generally used in combination with the include feature to help reusing macro at several places.
A macro is defined by writing the resolver it is equivalent to as if it were written in the resolver place, except that you can use attributes to pass parameters to the newly defined resolver type. Attributes are defined with a name and sometimes a default value, and are used using the following syntax: @{attributename}
.
Attribute | Description | Required |
---|---|---|
name | name of the resover type created | Yes |
Element | Description | Cardinality |
---|---|---|
attribute | defines an attribute for the macro resolver | 0..n |
any resolver | defines the base resolver upon which this macro is defined | 1 |
Defining a simple macro:
<macrodef name="mymacro">
<attribute name="mymainrep"/>
<filesystem name="fs1">
<ivy pattern="@{mymainrep}/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
<artifact pattern="@{mymainrep}/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
</macrodef>
<resolvers>
<mymacro name="default" mymainrep="path/to/myrep"/>
</resolvers>
<ivyconf>
<macrodef name="mymacro">
<attribute name="mymainrep"/>
<attribute name="mysecondrep"/>
<attribute name="myseconddirlayout" default="[organisation]/[module]/[type]s"/>
<chain>
<filesystem name="fs1">
<ivy pattern="@{mymainrep}/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
<artifact pattern="@{mymainrep}/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<filesystem name="fs2" latest="latest-time">
<ivy pattern="@{mysecondrep}/@{myseconddirlayout}/ivy-[revision].xml"/>
<artifact pattern="@{mysecondrep}/@{myseconddirlayout}/[artifact]-[revision].[ext]"/>
</filesystem>
</chain>
</macrodef>
<resolvers>
<mymacro name="default" mymainrep="path/to/myrep" mysecondrep="path/to/secondrep"/>
<mymacro name="other"
mymainrep="path/to/myrep"
mysecondrep="path/to/secondrep"
myseconddirlayout="[module]/[type]s"/>
</resolvers>
</ivyconf>
Tag: attribute
Defines a macrodef attribute. See macrodef for details.
Attribute | Description | Required |
---|---|---|
name | the name of the attribute | Yes |
default | the default value of the attribute if none is specified | No, by default attribute are required |
Tag: resolvers
Defines a list of dependency resolvers usable in ivy. Each dependency resolver is identified by its name, given as an attribute.
The child tag used for the dependency resolver must be equal to a name of a dependency resolver type (either built-in or added with the typedef tag).
since 1.3 Once defined, resolvers can be referenced by their name, using the following syntax:
<resolver ref="alreadydefinedresolver"/>
Element | Description | Cardinality |
---|---|---|
any resolver | adds a resolver to the list of available resolvers | 1..n |
Ivy comes with a set of built-in dependency resolvers able to answer to the most common needs.
If you don't find the one you want here, you can also check if some one has not contributed it in the links page, or even write your own.
<resolvers>
<filesystem name="1">
<ivy pattern="${ivy.conf.dir}/1/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${ivy.conf.dir}/1/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<chain name="chain1">
<resolver ref="1"/>
<ivyrep name="ivyrep"/>
</chain>
<chain name="chain2" returnFirst="true" dual="true">
<resolver ref="1"/>
<ibiblio name="ibiblio"/>
</chain>
</resolvers>
Tag | ivyrep |
Handle latest | yes, at least if the repository server is apache based |
Handle publish | no |
Attribute | Description | Required |
---|---|---|
name | the name which identify the resolver | Yes |
validate | indicates if resolved ivy files should be validated against ivy xsd | No, defaults to true |
checkmodified | Indicates if this resolver should check lastmodified date to know if an ivy file is up to date. | |
alwaysCheckExactRevision | Indicates if this resolver should check the given revision even if it's a special one (like latest.integration). since 1.3 | No, defaults to ${ivy.default.always.check.exact.revision} |
ivyroot | the root of the ivy repository. | No, defaults to ${ivy.ivyrep.default.ivy.root} |
ivypattern | a pattern describing the layout of the ivy repository. | No, defaults to ${ivy.ivyrep.default.ivy.pattern} |
artroot | the root of the artifacts repository. | No, defaults to ${ivy.ivyrep.default.artifact.root} |
artpattern | a pattern describing the layout of the artifacts repository. | No, defaults to ${ivy.ivyrep.default.artifact pattern} |
namespace | The name of the namespace to which this resolver belong since 1.3 | No, defaults to 'system' |
checkconsistency | true to check consistency of module descriptors found by this resolver, false to avoid consistency check since 1.3 | No, defaults to true |
latest | The name of the latest strategy to use. | No, defaults to 'default' |
Tag | ibiblio |
Handle latest | yes, at least if the repository server is apache based |
Handle publish | no |
This resolver usually uses ibiblio to find artifacts.
Prefer the use of ivyrep resolver which adds ivy file handling to this resolver.
since 1.3 Using the m2compatible attribute, you can benefit from maven 2 repository compatibility (convert dots in organisation in slashes, search for poms, use transitive dependencies of poms). This setting also affects the default place where the resolver look for its artifacts to point to the maven2 repository. So setting this attribute to true is sufficient to use maven 2 ibiblio repository.
Attribute | Description | Required |
---|---|---|
name | the name which identify the resolver | Yes |
validate | indicates if resolved ivy files should be validated against ivy xsd | No, defaults to call setting |
alwaysCheckExactRevision | Indicates if this resolver should check the given revision even if it's a special one (like latest.integration). since 1.3 | No, defaults to ${ivy.default.always.check.exact.revision} |
root | the root of the artifacts repository. | No, defaults to ${ivy.ibiblio.default.artifact.root} |
pattern | a pattern describing the layout of the artifacts repository. | No, defaults to ${ivy.ibiblio.default.artifact.pattern} |
m2compatible | True if this resolver should be maven2 compatible, false otherwise since 1.3 | No, defaults to false |
namespace | The name of the namespace to which this resolver belong since 1.3 | No, defaults to 'system' |
checkconsistency | true to check consistency of module descriptors found by this resolver, false to avoid consistency check since 1.3 | No, defaults to true |
latest | The name of the latest strategy to use. | No, defaults to 'default' |
Tag | filesystem |
Handle latest | yes |
Handle publish | yes |
Attribute | Description | Required |
---|---|---|
name | the name which identify the resolver | Yes |
validate | indicates if resolved ivy files should be validated against ivy xsd | No, defaults to call setting |
checkmodified | Indicates if this resolver should check lastmodified date to know if an ivy file is up to date. | No, defaults to ${ivy.resolver.default.check.modified} |
alwaysCheckExactRevision | Indicates if this resolver should check the given revision even if it's a special one (like latest.integration). since 1.3 | No, defaults to ${ivy.default.always.check.exact.revision} |
m2compatible | True if this resolver should be maven2 compatible, false otherwise since 1.3 | No, defaults to false |
namespace | The name of the namespace to which this resolver belong since 1.3 | No, defaults to 'system' |
checkconsistency | true to check consistency of module descriptors found by this resolver, false to avoid consistency check since 1.3 | No, defaults to true |
latest | The name of the latest strategy to use. | No, defaults to 'default' |
Element | Description | Cardinality |
---|---|---|
ivy | defines a pattern for ivy files, using the pattern attribute | 0..n |
artifact | defines a pattern for artifacts, using the pattern attribute | 1..n |
Tag | url |
Handle latest | yes with http urls (and apache server) and with file urls, no with other urls |
Handle publish | no |
Attribute | Description | Required |
---|---|---|
name | the name which identify the resolver | Yes |
validate | indicates if resolved ivy files should be validated against ivy xsd | No, defaults to call setting |
checkmodified | Indicates if this resolver should check lastmodified date to know if an ivy file is up to date. | No, defaults to ${ivy.resolver.default.check.modified} |
alwaysCheckExactRevision | Indicates if this resolver should check the given revision even if it's a special one (like latest.integration). since 1.3 | No, defaults to ${ivy.default.always.check.exact.revision} |
m2compatible | True if this resolver should be maven2 compatible, false otherwise since 1.3 | No, defaults to false |
namespace | The name of the namespace to which this resolver belong since 1.3 | No, defaults to 'system' |
checkconsistency | true to check consistency of module descriptors found by this resolver, false to avoid consistency check since 1.3 | No, defaults to true |
latest | The name of the latest strategy to use. | No, defaults to 'default' |
Element | Description | Cardinality |
---|---|---|
ivy | defines a pattern for ivy files, using the pattern attribute | 0..n |
artifact | defines a pattern for artifacts, using the pattern attribute | 1..n |
Tag | chain |
Handle latest | depends on sub resolvers |
Handle publish | delegates to first sub resolver in chain |
This resolver is only a container of a chain of other resolvers. The sub resolvers can be any resolver, including a chain. An attribute enable to indicate if the chain must be iterated after the first found or not (at least when asking for a latest revision). If the chain is iterated, then it's the latest among the ones found that is returned. If the chain is not iterated, then it's the first found which is returned.
Attribute | Description | Required |
---|---|---|
name | the name which identify the resolver | Yes |
validate | indicates if resolved ivy files should be validated against ivy xsd | No, defaults to call setting |
returnFirst | true if the first found should be returned. | No, defaults to false |
dual | true if the chain should behave like a dual chain. since 1.3 | No, defaults to false |
namespace | The name of the namespace to which this resolver belong since 1.3 | No, defaults to 'system' |
latest | The name of the latest strategy to use. | No, defaults to 'default' |
Element | Description | Cardinality |
---|---|---|
any resolver | a sub resolver to use | 1..n |
<chain name="test">
<filesystem name="1">
<ivy pattern="${ivy.conf.dir}/1/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${ivy.conf.dir}/1/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<ivyrep name="2"/>
</chain>
<chain name="test" returnFirst="true">
<filesystem name="1">
<ivy pattern="${ivy.conf.dir}/1/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${ivy.conf.dir}/1/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<ivyrep name="2"/>
</chain>
<chain name="test" dual="true">
<filesystem name="1">
<ivy pattern="${ivy.conf.dir}/1/[organisation]/[module]/ivys/ivy-[revision].xml"/>
<artifact pattern="${ivy.conf.dir}/1/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<ivyrep name="2"/>
</chain>
Tag | dual |
Handle latest | depends on sub resolvers |
Handle publish | delegates to ivy sub resolver if artifact to publish is of "ivy" type, to artifact sub resolver otherwise |
Attribute | Description | Required |
---|---|---|
name | the name which identify the resolver | Yes |
validate | indicates if resolved ivy files should be validated against ivy xsd | No, defaults to call setting |
namespace | The name of the namespace to which this resolver belong since 1.3 | No, defaults to 'system' |
latest | The name of the latest strategy to use. | No, defaults to 'default' |
Element | Description | Cardinality |
---|---|---|
any resolver | two resolvers, the first being the ivy resolver, the second the artifact resolver | 2 |
Element | Description | Cardinality |
---|---|---|
any conflict manager | adds a conflict manager to the list of available conflict managers | 0..n |
Element | Description | Cardinality |
---|---|---|
module | defines a module set rule | 1..n |
Tag: module
Define a resolver application rule. The tag defines a module set, by giving an expression and the matcher to use for organisation and name (for instance, you can use
* to specify all). It also gives the name of the resolver to use for this module set.
Attribute | Description | Required |
---|---|---|
organisation | the name of the organisation to which apply the resolver. May be a regexp. | Yes |
name | the name of the module to which apply the resolver. May be a regexp. | Yes |
matcher | the matcher to use to match the modules to which the resolver should be applied since 1.3 | No, defaults to exactOrRegexp in pre 1.3 ivy files, and exact in 1.3 and superior |
resolver | the name of the resolver to apply. The resolver must have been defined in the resolvers section of the configuration file. | Yes |
<modules>
<module organisation="jayasoft" name="*" resolver="myprojectsresolver"/>
</modules>
<modules>
<module organisation="apache" name="commons-*" matcher="glob" resolver="myapachecommonsresolver"/>
</modules>
<modules>
<module organisation="apache" name="commons-[a-z]+" matcher="regexp" resolver="myapachecommonsresolver"/>
</modules>
Ivy use is entirely based on what is called ivy files. Ivy files are xml files, usually called ivy.xml, containing the description of the dependencies of a module, its published artifacts and its configurations.
Here is the simplest ivy file you can write:
<ivy-module version="1.3">
<info organisation="myorg"
module="mymodule"
/>
</ivy-module>
Since version 0.8, ivy publishes an xslt which help make ivy files more readable. You just have to add
a line like this one in your ivy file:
<?xml-stylesheet type="text/xsl" href="http://www.ivyrep.org/ivy-doc.xsl"?>
However, all information is not presented with the xslt (dependency configurations, in particular).
And due to security issues, it only works if the ivy file is in the same domain as the xsl... But they are particularly useful to browse the ivy repository.
If you want to see a sample file using almost all possibilities of ivy files, check this one, with or without xslt.
Before beginning the reference itself, it is required to have in mind the terminology defined in the main page of this reference documentation.
For those familiar with xml schema, the schema used to validate ivy files can be found here. For those using xsd aware IDE, you can declare the xsd in your ivy files to benefit from code completion / validation:
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=
"http://www.jayasoft.org/misc/ivy/ivy.xsd">
<info organisation="myorg"
module="mymodule"
/>
</ivy-module>
ivy-module info license ivyauthor repository description configurations conf publications artifact conf dependencies dependency conf mapped artifact conf include conf exclude conf conflicts manager
Tag: ivy-module
Root tag of any ivy-file.
Attribute | Description | Required |
---|---|---|
version | the version of the ivy file specification - should be '1.3' with current version of ivy | Yes |
Element | Description | Cardinality |
---|---|---|
info | contains information about the described module | 1 |
configurations | container for configuration elements | 0..1 |
publications | container for published artifact elements | 0..1 |
dependencies | container for dependency elements | 0..1 |
conflicts | section to configure the conflict managers to use | 0..1 |
Attribute | Description | Required |
---|---|---|
organisation | the name of the organisation that is the owner of this module. | Yes |
module | the name of the module described by this ivy file. | Yes |
revision | the revision of this module. | Yes in repository ivy files, no in ivy files to resolve |
status | the status of this module. See terminology section for details | No, default to 'integration' |
publication | the date of publication of this module. It should be given in this format: yyyyMMddHHmmss | No, but it's a good practice to set it with delivered ivy files |
Element | Description | Cardinality |
---|---|---|
license | contains information about the licenses of the described module | 0..n |
ivyauthor | describes who has contributed to write the ivy file | 0..n |
repository | describes on which public repositories this module can be found | 0..n |
description | describes how to use the module | 0..1 |
Attribute | Description | Required |
---|---|---|
name | the name of the license. Try to respect spelling when using a classical license. | Yes |
url | an url pointing to the license text. | No, but it's a good practice to indicate it |
Attribute | Description | Required |
---|---|---|
name | the name of the author, as a person or a company. | Yes |
url | an url pointing to where the author can bea reached. | No, but it's a good practice to indicate it |
Attribute | Description | Required |
---|---|---|
name | the name of the repository. Try to respect spelling for common repositories (ibiblio, ivyrep, ...) | Yes |
url | an url pointing to the repository. | Yes |
pattern | an ivy pattern to find modules on this repository | No, but it's recommended to indicate it. |
ivys | true if ivy file can be found on this repository | No, defaults to false. |
artifacts | true if module artifacts can be found on this repository | No, defaults to false. |
Attribute | Description | Required |
---|---|---|
homepage | the url of the homepage of the module | No, but it's recommended to indicate it. |
Tag: configurations Parent: ivy-module
Container for configuration element. If this container is not present, it is assumed that the module has one public configuration called 'default'.
since 1.3 You can define a new default conf mapping on this container by specifying the defaultconfmapping attribute.
A default conf mapping is very similar to the defaultconf which can be set on the dependencies tag, but it has a slightly different behaviour.
The default conf mapping not only defines the conf mapping to use when no conf mapping is specified for a dependency in this ivy file, but it also modify the way ivy interprets conf mapping with no mapped conf. In this case, Ivy will look in the default conf mapping and use the conf mapping defined in the default conf mapping for the conf for which there is no mapped conf.
For instance, if you define runtime->*;test->test
as default conf mapping, then if you have a dependency declared like this:
<dependency name="dep" rev="1.0" />
<dependency name="dep" rev="1.0" conf="runtime->*;test->test"/>
<dependency name="dep" rev="1.0" conf="runtime"/>
<dependency name="dep" rev="1.0" conf="runtime->*"/>
<dependency name="dep" rev="1.0" conf="runtime->runtime"/>
Attribute | Description | Required |
---|---|---|
defaultconfmapping | the default conf mapping to use in this ivy file since 1.3 | No, defaults to no default conf mapping |
Element | Description | Cardinality |
---|---|---|
conf | declares a configuration of this module | 0..n |
include | include configurations from another file | 0..n |
Attribute | Description | Required |
---|---|---|
name | the name of the declared configuration | Yes |
description | a description for the declared configuration | No |
visibility | the visibility of the declared configuration. 'public' means that this configuration can be used by other modules, while 'private' means that this configuration is used only in the module itself, and is not exposed to other modules | No, defaults to public |
extends | a comma separated list of configurations of this module that the current configuration extends | No, defaults to none |
deprecated | indicates that this conf has been deprecated by giving the date of the deprecation. It should be given in this format: yyyyMMddHHmmss | No, by default the conf is not deprecated |
Tag: include Parent: configurations
Include configurations specified in another file. since 1.3
The included file should have a configurations tag as root tag, which follow the same specification as the configurations tag of the ivy file.
This means that it can contain conf declarations, other file inclusion, and also a defaultconfmapping.
Attribute | Description | Required |
---|---|---|
file | the file to include | Yes |
<ivy-module version="1.0">
<info organisation="myorg"
module="mymodule"
/>
<configurations>
<include file="path/to/included-configurations.xml"/>
<conf name="conf3"/>
</configurations>
<dependencies>
<dependency name="mymodule1" rev="1.0"/>
<dependency name="mymodule2" rev="2.0" conf="conf2,conf3->*"/>
</dependencies>
</ivy-module>
<configurations defaultconfmapping="*->@">
<conf name="conf1" visibility="public"/>
<conf name="conf2" visibility="private"/>
</configurations>
Element | Description | Cardinality |
---|---|---|
artifact | declares a published artifact for this module | 0..n |
Attribute | Description | Required |
---|---|---|
name | the name of the published artifact. This name must not include revision. | Yes |
type | the type of the published artifact. It's usually its extension, but not necessarily. For instance, ivy files are of type 'ivy' but have 'xml' extension | Yes |
ext | the extension of the published artifact | No, defaults to type |
conf | comma separated list of public configurations in which this artifact is published. '*' wildcard can be used to designate all public configurations of this module | No, defaults to 'default' if neither conf attribute nor conf children element is given |
Element | Description | Cardinality |
---|---|---|
conf | indicates a public configuration in which this artifact is published | 0..n |
Attribute | Description | Required |
---|---|---|
name | the name of the module public configuration in which this artifact is published. '*' wildcard can be used to designate all public configurations of this module | Yes |
Tag: dependencies Parent: ivy-module
Container for dependency elements, used to describe the dependencies of this module.
If this container is not present, it is assumed that the module has no dependency at all.
This container let the possibility to defines two very similar things: defaultconf and defaultconfmapping.
defaultconf
exists since Ivy 1.1 and enables to define the default conf attribute to use when no conf is defined for a dependency in this ivy file. It is only used when no conf mapping is defined, and has no influence in other cases.
defaultconfmapping
exists since Ivy 1.3 and enables not only to define the default conf mapping when no conf is specified for a dependency in this ivy file, but it also influence the way conf mapping with no mapped conf are interpreted (see configurations doc page for details about this).
Note that if both defaultconf and defaultconfmapping are defined, it's the defaultconfmapping that is used. Note also that if several defaultconfmapping are defined (one in the configurations tag, one or several in included configurations file, and/or one in the dependency tag, then it's only the last which is taken into account, the others will have no effect at all.
Attribute | Description | Required |
---|---|---|
defaultconf | the default configuration to use when none is specified in a dependency. since 1.1 | No, defaults to *->* |
defaultconfmapping | the default configuration mapping to use in this ivy fie. since 1.3 | No, defaults to no default conf mapping |
Element | Description | Cardinality |
---|---|---|
dependency | declares a dependency for this module | 1..n |
Tag: dependency Parent: dependencies
Declares a dependency for this module. A dependency is described by the module on which the current module depends (identified by its name, organisation and revision), and a mapping of configurations.
The revision can be given as a fixed one (1.5.2, for instance) or as a latest one. Two possibilities are offered for the moment:
The way to determine which revision is the "latest" between two is configurable through the use of pluggable LatestStrategy. See ivy main concepts for details about this.
This mapping indicates which configurations of the dependency are required in which configurations of the current module, also called master configurations.
There are several ways to declare this mapping of configurations, choose depending more on preference than on possibilities. Try to avoid mixing usage in a single dependency element: do not use both nested and inline mapping declaration.
The first way to declare this mapping is called the inline mapping. It is maybe the less natural at first, but it's powerful and concise. Inline mapping can take several forms.
In this case, all specified dependency configurations are required in all specified master configurations.
For instance, 'A, B, C -> E, F' means that dependency configurations E & F are required in master configurations A, B and C.
Note that you can use the wildcard '*' as a configuration name, meaning that all configurations (either master or dependency public ones depending on the side) are wanted. For instance, '* -> B, C' means that B & C dependency configurations are required in all master configurations.
since 1.2 '@' also has a special meaning as a right operand of the dependency mapping, it means map to self. This is particularly useful with '*', '*->@' meaning that all configurations of the module maps to their equivalent (same name) in the dependency.
since 1.3 a fallback mechanism can be used when you are not sure that the dependency will have the required conf. You can indicate to ivy that you want one configuration, but if it isn't present, use another one.
The syntax for specifying this adds the fallback conf between parenthesis right after the required conf.
For instance, test->runtime(default)
means that in the test configuration of the module the runtime
conf of the dependency is required, but if doesn't exist, it will use the default
conf instead. If default
conf doesn't exist then it will be considered as an error. Note that the *
wildcard can be used as fallback conf.
If you prefer more verbose mapping declaration, everything is also possible with sub elements mapping declaration.
Moreover, the dependency element also supports an artifact restriction feature (since 0.6).
See dependency artifact restriction for details.
Finally, the dependency element also supports an a force attribute (since 0.8), which gives an indication
to conflicts manager to force the revision of a dependency to the one given here.
See conflicts manager for details.
Attribute | Description | Required |
---|---|---|
org | the name of the organisation of the dependency. | No, defaults to the master module organisation |
name | the module name of the dependency | Yes |
rev | the revision of the dependency. Use 'latest.integration' to get the latest version of the dependency. You can also end the revision asked with a '+' to get the latest matching revision. Both latest works only with some dependency resolvers (see configuration) | Yes |
force | a boolean to give an indication to conflict manager that this dependency should be forced to this revision (see conflicts manager) |
No, defaults to false |
conf | an inline mapping configuration spec (see above for details) | No, defaults to defaultconf attribute of dependencies element if neither conf attribute nor conf children element is given |
transitive | true to resolve this dependency transitively, false otherwise (since 1.2) | No, defaults to true |
changing | true if the dependency artifacts may change without revision change, false otherwise (since 1.2). Artifacts update will be looked after only if the publication date of the ivy file has changed. Note that this is not a recommended use and that it avoid some cache optimization in ivy. | No, defaults to false |
Element | Description | Cardinality |
---|---|---|
conf | defines configuration mapping has sub element | 0..n |
artifact / include | defines artifacts inclusion - use only if you do not control dependency ivy file | 0..n |
exclude | defines artifacts exclusion - use only if you do not control dependency ivy file | 0..n |
<dependency org="jayasoft" name="swtbinding" revision="0.2"/>
<dependency name="mymodule" revision="latest.integration" conf="test->default"/>
mymodule
from the same organisation as the module in which the dependency is declared. The latest available revision of this dependency will be used. This dependency will only be included in the test configuration of the module, and it's only the default configuration of the dependency which will be included.<dependency org="apache" name="commons-lang" revision="2.0" force="true" conf="default"/>
commons-lang
from apache, in revision 2.0. The revision 2.0 will be used even if another dependency declares itself a dependency on another version of commons-lang. Moreover, if no defaultconfmapping is defined, only the default
conf of commons-lang will be used in the default
conf of the master module. If *->runtime
was declared as defaultconfmapping, then the runtime conf of commons-lang would be included in the default conf of the master module. Note that whatever the defaultconfmapping is, the dependency only be included in the default conf of the master module. The defaultconfmapping only changes the required dependency confs.<dependency org="foo" name="bar" revision="3.0" transitive="false" conf="default->@;runtime,test->runtime"/>
bar
from foo, in revision 3.0. The dependencies of bar will themselves not be included due to the setting of transitive. The default dependency conf will be included in the default master conf, and the runtime dependency conf will be included in both the runtime and test master conf.<dependency org="foo" name="bar" revision="3.0" changing="true" conf="compile->runtime(default)"/>
bar
from foo, in revision 3.0. This revision is considered to be able to change (changing="true"
), so even if it is already in ivy cache, Ivy will check if a revision is a more recent last modified date is available on the repository. The runtime conf of bar is required in the compile conf of the master module, but if bar doesn't define a runtime conf, then the default
conf will be used.
Attribute | Description | Required |
---|---|---|
name | the name of the master configuration to map. '*' wildcard can be used to designate all configurations of this module | Yes |
mapped | a comma separated list of dependency configurations to which this master configuration should be mapped | No, default to the same configuration as master one, unless nested mapped elements are specified |
Element | Description | Cardinality |
---|---|---|
mapped | map dependency configurations for this master configuration | 0..n |
Attribute | Description | Required |
---|---|---|
name | the name of the dependency configuration mapped. '*' wildcard can be used to designate all configurations of this module | Yes |
<dependency org="yourorg" name="yourmodule9" rev="9.1" conf="A,B->default"> <artifact name="art1" type="jar" conf="A,B"/> <artifact name="art2" type="jar" conf="A"/> </dependency>
Attribute | Description | Required |
---|---|---|
name | the name of an artifact of the dependency module to add to the include list, or a regexp matching this name | No, defaults to .* |
type | the type of the artifact of the dependency module to add to the include list, or a regexp matching this name | No, defaults to .* |
ext | the extension of the artifact of the dependency module to add to the include list, or a regexp matching this name | No, defaults to type |
conf | comma separated list of the master configurations in which this artifact should be included. '*' wildcard can be used to designate all configurations of this module | No, defaults to '*', unless nested conf are specified |
Element | Description | Cardinality |
---|---|---|
conf | configuration in which the artifact should be included | 0..n |
Attribute | Description | Required |
---|---|---|
name | the name of the master configuration in which the enclosing artifact should be included | Yes |
Tag: exclude Parent: dependency
This feature gives you more control on a dependency for which you do not control its ivy file.
It enables to restrict the artifacts required, by excluding artifacts being published by the dependency or any of its transitive dependencies,
even if configuration does not a good separation of published artifacts
The same principle concerning configuration as for include applies to this exclude feature (see above the include feature).
Note that exclusion is always done AFTER inclusion has been done.
since 1.3 This exclude feature can also be used not only to exclude artifacts but also to exclude whole modules. Indeed when you exclude artifacts, it doesn't avoid ivy to search for the module itself, and to resolve the dependencies of the module. But you can also exclude the whole module, which means that the module will not be downloaded at all, and so its own dependencies will not be resolved. For sure, this is usually done to exclude not a direct dependency but an indirect one. To exclude a whole module, you just have to not specify any artifact name, type and ext in your exclude rule. For instance:
<dependency name="A" rev="1.0">
<exclude module="B"/>
</dependency>
Attribute | Description | Required |
---|---|---|
org | the organisation of the dependency module or artifact to exclude, or a regexp matching this organisation since 1.3 | No, defaults to * |
module | the name of the dependency module or the artifact to exclude, or a regexp matching this module name since 1.3 | No, defaults to * |
name | the name of an artifact of the dependency module to add to the exclude list, or a regexp matching this name | No, defaults to * |
type | the type of the artifact of the dependency module to add to the exclude list, or a regexp matching this name | No, defaults to * |
ext | the extension of the artifact of the dependency module to add to the exclude list, or a regexp matching this name | No, defaults to type |
matcher | the matcher to use to match the modules to excludes since 1.3 | No, defaults to exactOrRegexp in pre 1.3 ivy files, and exact in 1.3 and superior |
conf | comma separated list of the master configurations in which this artifact should be included. '*' wildcard can be used to designate all configurations of this module |
No, defaults to '*', unless nested conf are specified |
Element | Description | Cardinality |
---|---|---|
conf | configuration in which the artifact should be included | 0..n |
Attribute | Description | Required |
---|---|---|
name | the name of the master configuration in which the enclosing artifact should be excluded | Yes |
Element | Description | Cardinality |
---|---|---|
manager | declares a conflict manager for this module | 1..n |
Attribute | Description | Required |
---|---|---|
org | the name, or a regexp matching the name of organisation to which this conflict manager should apply | No, defaults to * (match all) |
module | the name, or a regexp matching the name of module to which this conflict manager should apply | No, defaults to * (match all) |
name | the name of the conflict manager to use | Exactly one of two |
rev | a comma separated list of revisions this conflict manager should select | |
matcher | the matcher to use to match the modules for which the conflict manager should be used since 1.3 | No, defaults to exactOrRegexp in pre 1.3 ivy files, and exact in 1.3 and superior |
The main and most frequent way to use ivy is from an ant build file. However, ivy can also be called as a standalone application
The main and most frequent way to use ivy is from an ant build file. However, ivy can also be called as a standalone application
If you use ant version 1.6.0 or superior, you just have to add ivy namespace to your project (xmlns:ivy="antlib:fr.jayasoft.ivy.ant"
attribute of your project tag), and you can call ivy tasks.
If you want to make your build handle ivy.jar in either ant lib dir or a local lib dir, you can follow this tip given by colin sampaleanu.
If you use ant 1.5.1 or superior, you have to define the tasks in your build file:
<taskdef name="ivy-configure" classname="fr.jayasoft.ivy.ant.IvyConfigure"/>
<taskdef name="ivy-resolve" classname="fr.jayasoft.ivy.ant.IvyResolve"/>
<taskdef name="ivy-retrieve" classname="fr.jayasoft.ivy.ant.IvyRetrieve"/>
<taskdef name="ivy-deliver" classname="fr.jayasoft.ivy.ant.IvyDeliver"/>
<taskdef name="ivy-publish" classname="fr.jayasoft.ivy.ant.IvyPublish"/>
If you use an ant version lower than 1.5.1, you can not use the ivy tasks... you should then call ivy as any external program.
Once your build file is ok to call ivy tasks, the simplest way to use ivy is to call the ivy retrieve task with no parameters:
<ivy:retrieve />
<target name="resolve">
<ivy:configure />
<ivy:resolve file="${ivy.dep.file}" conf="${ivy.configurations}" />
<ivy:retrieve pattern="${ivy.retrieve.pattern}" conf="${ivy.configurations}" />
</target>
Those 3 tasks follow the 3 main steps of ivy retrieving dependencies process:
To understand more accurately the behaviour of ivy tasks, one should know that a property file is loaded in ant by ivy at the beginning of the configure call. This property file contains the following properties:
ivy.project.dir = ${basedir}
ivy.lib.dir = ${ivy.project.dir}/lib
ivy.build.artifacts.dir = ${ivy.project.dir}/build/artifacts
ivy.distrib.dir = ${ivy.project.dir}/distrib
ivy.configurations = *
ivy.resolver.default.check.modified = false
ivy.resolve.default.type.filter = *
ivy.status = integration
ivy.dep.file = ivy.xml
ivy.conf.file = ivyconf.xml
ivy.retrieve.pattern = ${ivy.lib.dir}/[artifact]-[revision].[ext]
ivy.deliver.ivy.pattern = ${ivy.distrib.dir}/[type]s/[artifact]-[revision].[ext]
ivy.publish.src.artifacts.pattern = ${ivy.distrib.dir}/[type]s/[artifact]-[revision].[ext]
ivy.report.output.pattern = [organisation]-[module]-[conf].html
ivy.buildlist.ivyfilepath = ivy.xml
Some tasks attributes values may be given through different places. The three possible places are :
The places are queried in this order, so anything set in task attribute will overwrite what would have been found in ivy instance, for example.
The ivy instance considered here is an instance of the class Ivy, which is setup by a call to the configure task, and then reused for other tasks. Because most of the tasks need an ivy instance, they first check if one is available (i.e. configure has been called), and if none is available, then a default configure is called and the resulting ivy instance is used in the remaining tasks (unless another configure is called).
It isn't generally necessary to understand this, but it can lead to some issues if you forget to call configure before another task and if the configure step was required in your environment.
Here is a more complete example of build file using ivy:
<project xmlns:ivy="antlib:fr.jayasoft.ivy.ant" name="sample" default="resolve">
<target name="resolve">
<ivy:configure file="../ivyconf.xml" />
<ivy:resolve file="my-ivy.xml" conf="default, myconf" />
</target>
<target name="retrieve-default" depends="resolve">
<ivy:retrieve pattern="lib/default/[artifact]-[revision].[ext]" conf="default" />
</target>
<target name="retrieve-myconf" depends="resolve">
<ivy:retrieve pattern="lib/myconf/[artifact]-[revision].[ext]" conf="myconf" />
</target>
<target name="retrieve-all" depends="resolve">
<ivy:retrieve pattern="lib/[conf]/[artifact]-[revision].[ext]" conf="*" />
</target>
<target name="deliver" depends="retrieve-all">
<ivy:deliver deliverpattern="distrib/[artifact]-[revision].[ext]" pubrevision="1.1b4" pubdate="20050115123254" status="milestone" />
</target>
<target name="publish" depends="deliver">
<ivy:publish resolver="internal" artifactspattern="distrib/[artifact]-[revision].[ext]" pubrevision="1.1b4" />
</target>
</project>
Attribute | Description | Required |
---|---|---|
file | path to the configuration file to use | No. If a file is provided, url is ignored. If none are provided, then it attempts to find a file at ${ivy.conf.file}, and if this file does not exist, it uses a default configuration file |
url | url of the configuration file to use | |
host | http authentication host | No, unless authentication is required |
realm | http authentication realm | |
username | http authentication user name | |
passwd | http authentication password |
<ivy:configure />Use either ${ivy.conf.file} if it exists, or the default configuration file
<ivy:configure file="myconffile.xml" />
<ivy:configure url="http://mysite.com/myconffile.xml" />
The resolve task actually resolve dependencies described in an ivy file, and put the resolved dependencies in the ivy cache.
If configure has not been called before resolve is called, a default configuration will be used (equivalent to call configure with no attributes).
After the call to this task, four properties are set in ant:
set to the organisation name found in the ivyfile which was used for resolve
set to the module name found in the ivyfile which was used for resolve
set to the revision name found in the ivyfile which was used for resolve, or a generated revision name if no revision was specified in the file
set to the comma separated list of configurations resolved
An additional property is set only if there are changes since the last resolve: ivy.deps.changed
(since 1.2)
When ivy has finished the resolve task, it outputs a summary of what has been resolved. This summary looks like this:
--------------------------------------------------------------------- | | modules || artifacts | | conf | number| search|dwnlded|evicted|| number|dwnlded| --------------------------------------------------------------------- | default | 4 | 0 | 0 | 0 || 4 | 0 | ---------------------------------------------------------------------
This table gives some statistics about the dependency resolution. Each line correspond to a configuration resolved. Then the table is divided in two parts:
This is the total number of dependency modules resolved in this configuration, including transitive ones
This is the number of dependency modules that required a repository access. The repository access is needed if the module is not yet in cache, or if a latest version is required, or in some other cases (depending on checkModified, for instance)
This is the number of dependency ivy files downloaded from the repository. This number can be less than the total number of modules even with a clean cache, if no ivy file is provided for some dependencies.
This is the number of dependency module evicted by conflict managers.
This is the total number of artifacts resolved in the given configuration.
This is the number of artifacts actually downloaded from the repository.
Note for developers:
After the call to this task, a reference to the module descriptor resolved is put in the ant project under the id "ivy.resolved.descriptor"
.
Attribute | Description | Required |
---|---|---|
file | path to the ivy file to use for resolution | No. Defaults to ${ivy.dep.file} |
conf | a comma separated list of the configurations to resolve | No. Defaults to ${ivy.configurations} |
type | comma separated list of accepted artifact types (since 1.2) | No. defaults to ${ivy.resolve.default.type.filter} |
haltonfailure | true to halt the build on ivy failure, false to continue | No. Defaults to true |
showprogress | true to show dots while downloading, false otherwise | No. Defaults to true |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
<ivy:resolve file="path/to/ivy.xml"/>
<ivy:resolve file="path/to/ivy.xml" conf="default, test"/>
<ivy:resolve file="path/to/ivy.xml" type="jar"/>
The retrieve task copies resolved dependencies anywhere you want in your file system.
If no resolve has been called before retrieve is called, a default resolve is called (equivalent to a call to resolve with no attributes).
Attribute | Description | Required |
---|---|---|
pattern | the pattern to use to copy the dependencies | No. Defaults to ${ivy.retrieve.pattern} |
ivypattern | the pattern to use to copy the ivy files of dependencies since 1.3 | No. Dependencies ivy files are not retrieved by default. |
conf | a comma separated list of the configurations to retrieve | No. Defaults to the configurations resolved by the last resolve call, or * if no resolve was explicitly called |
organisation | the organisation of the module to retrieve. This usually doesn't need to be set since it defaults to the last resolved one. | No. Defaults to last resolved organisation |
module | the name of the module to retrieve. This usually doesn't need to be set since it defaults to the last resolved one. | No. Defaults to last resolved module name |
haltonfailure | true to halt the build on ivy failure, false to continue | No. Defaults to true |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
<ivy:retrieve />
<ivy:retrieve pattern="${lib.dir}/[conf]/[artifact].[ext]"/>
lib
default
commons-lang.jar
commons-logging.jar
test
junit.jar
<ivy:retrieve pattern="${lib.dir}/[type]/[artifact]-[revision].[ext]" conf="runtime"/>
runtime
configuration in directories named by artifact type. The resulting lib dir could look like this:lib
jar
commons-lang-1.0.jar
looks-1.1.jar
source
looks-1.1.zip
Delivers a resolved ivy file of the current module, and possibly do recursive delivery of dependencies.
This task does two main things:
This task delivers a resolved ivy file of the current module, based upon the last resolve done. The resolved ivy file contains updated information about the delivered module, such as revision and status.
Moreover, all included configurations files are included in the ivy file, and variables are replaced by their values.
Finally, in the resolved ivy file, dynamic revisions are replaced by the static ones that have been found during the resolve step, so the ivy file can be used later safely to obtain the same dependencies (providing that a revision uniquely identifies a module, which should be the case for proper ivy use).
since 1.3 The replacement of dynamic revisions by static ones can be turned off, so that dynamic revisions are kept in the ivy file.
This is done only if a deliver target is given to the deliver task.
If a deliver target is set, then it is called for each dependency which has not a suffisant status compared to the deliver status set for this task. This means that if you deliver an integration revision, no recursive delivery will be done.
If you deliver a milestone revision, deliver target will be called with each integration dependency.
Finally, if you deliver a release revision, then deliver target will be called with each integration and milestone dependency.
The deliver target is called with the following properties available:
the name of the dependency to recursively deliver
the status to which the dependency should be delivered
the revision to which the dependency should be delivered
the revision of the dependency that should be delivered (the one that was retrieved during last resolve)
Note that both dependency.published.status
and dependency.published.version
are in fact asked to the user via standard ant input. The delivered ivy file will update its dependency revisions with those given here.
Attribute | Description | Required |
---|---|---|
deliverpattern | the pattern to use for ivy file delivery | No. Defaults to ${ivy.deliver.ivy.pattern} |
pubrevision | the revision to use for the publication | No. Defaults to the ${ivy.deliver.revision} |
pubdate | the publication date to use for the publication. This date should be either 'now', or a date given with the following pattern: yyyyMMddHHmmss | No. Defaults to 'now' |
status | the status to use for the publication | No. Defaults to ${ivy.status} |
delivertarget | the target to call for recursive delivery | No. No recursive delivery is done by default |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
replacedynamicrev | true to replace dynmic revisions by static ones in the delivered file, false to avoid this replacement since 1.3 | No. Defaults to true |
Attribute | Description | Required |
---|---|---|
artifactspattern | the pattern to use to find artifacts to publish | No. Defaults to ${ivy.publish.src.artifacts.pattern} |
resolver | the name of the resolver to use for publication | Yes |
pubrevision | the revision to use for the publication | No. Defaults to the ${ivy.deliver.revision} |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
replacedynamicrev | true to replace dynmic revisions by static ones in the delivered file, false to avoid this replacement since 1.3 | No. Defaults to true |
publishivy | True to publish delivered ivy file, false otherwise | No. Defaults to true |
warnonmissing | True to warn when artifacts to be published are missing | No. Defaults to true |
haltonmissing | True to halt build when artifacts to be published are missing | No. Defaults to true |
srcivypattern | the pattern to use to find ivy file to publish, and even deliver if necessary (since 1.2) | No. Defaults to the value of artifactspattern |
pubdate | the publication date to use for the delivery, if necessary. This date should be either 'now', or a date given with the following pattern: yyyyMMddHHmmss | No. Defaults to 'now' |
status | the status to use for the delivery, if necessary | No. Defaults to ${ivy.status} |
delivertarget | the target to call for recursive delivery | No. No recursive delivery is done by default |
Constructs an ant fileset consisting of artifacts in ivy cache for a configuration (since 1.2).
This task is usually used after a resolve, and can be used instead of retrieve. Note that this task
does not rely on retrieve, because built fileset is made of artifacts direcly in ivy cache.
Please prefer the use of retrieve + standard ant path creation, which make your build
more independent from ivy (once artifacts are properly retrieved, ivy is not required any more).
Built fileset is registered in ant with a given id, and can thus be used like any other ant fileset using
refid.
Attribute | Description | Required |
---|---|---|
setid | the id to reference the built fileset | Yes |
conf | a comma separated list of the configurations to put in the created path | No. Defaults to the configurations resolved by the last resolve call, or * if no resolve was explicitly called |
organisation | the organisation of the module for which the fileset should be built | No. Defaults to the organisation of the last resolved module in the same build. |
module | the name of the module for which the fileset should be built | No. Defaults to the name of the last resolved module in the same build. |
type | comma separated list of artifact types to accept in the path, * for all | No. Defaults to * |
haltonfailure | true to halt the build on ivy failure, false to continue | No. Defaults to true |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
Attribute | Description | Required |
---|---|---|
pathid | the id to reference the built path | Yes |
conf | a comma separated list of the configurations to put in the created path | No. Defaults to the configurations resolved by the last resolve call, or * if no resolve was explicitly called |
organisation | the organisation of the module for which the path should be built | No. Defaults to the organisation of the last resolved module in the same build. |
module | the name of the module for which the path should be built | No. Defaults to the name of the last resolved module in the same build. |
type | comma separated list of artifact types to accept in the path, * for all (since 1.2) | No. Defaults to * |
haltonfailure | true to halt the build on ivy failure, false to continue | No. Defaults to true |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
Attribute | Description | Required |
---|---|---|
todir | the directory to which reports should be generated | No, defaults to ${ivy.report.todir}, or execution directory if not defined |
outputpattern | the generated report names pattern | No, defaults to ${ivy.report.output.pattern}, or [organisation]-[module]-[conf].html if not defined |
xsl | true to generate a report (by default html report) using xslt, false otherwise since 1.3 | No, defaults to true |
xml | true to generate a xml report, false otherwise since 1.3 | No, defaults to false |
graph | true to generate graphml files, false otherwise | No, defaults to true |
conf | a comma separated list of the configurations for which a report should be generated | No. Defaults to the configurations resolved by the last resolve call (during same ant build), or ${ivy.resolved.configurations} if no resolve was called |
organisation | the name of the organisation of the module for which report should be generated | No, unless no resolve was called during the build. Defaults to last resolved module organisation. |
module | the name of the module for which report should be generated | No, unless no resolve was called during the build. Defaults to last resolved module. |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
xslfile | indicates which xsl file should be used to generate the report | No, defaults to ivy provided xsl which generates html report |
Installs a module and all its dependencies in a resolver. since 1.3
The module to install should be available in a resolver, and will be installed in another resolver which should support publish.
This is particularly useful for users who only have a private repository, and want to benefit from public repositories from time to time. In this case, when a module is missing in the private repository, a call to install let download the module from a public repository not usually used for dependency resolution, and install it and its dependencies in the private repository.
Attribute | Description | Required |
---|---|---|
from | the name of the resolver in which the module must be found | Yes |
to | the name of the resolver in which the module must be installed | Yes |
organisation | the name of the organisation of the module to install | Yes |
module | the name of the module to install | Yes |
revision | the revision of the module to install | Yes |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
overwrite | true to override modules already present in the destination resolver, false otherwise | No, defaults to false |
transitive | true to install the module and all its transitive dependencies, false to install only the module | No, defaults to false |
matcher | the name of the matcher to use to find the modules to install | No, defaults to exact |
<ivy:install organisation="apache" module="commons-lang" revision="2.0" from="ivyrep" to="myfsresolver"/>
Please prefer the use of retrieve + standard ant path creation, which make your build more independent from ivy (once artifacts are properly retrieved, ivy is not required any more).
The property name and value are generated using the classical pattern concept, all artifact tokens and ivy variables being available.
Attribute | Description | Required |
---|---|---|
name | a pattern used to generate the name of the properties to set | Yes |
value | a pattern used to generate the value of the properties to set | Yes |
conf | a comma separated list of the configurations for which properties should be set | No. Defaults to the configurations resolved by the last resolve call, or * if no resolve was explicitly called |
haltonfailure | true to halt the build on ivy failure, false to continue | No. Defaults to true |
validate | true to force ivy files validation against ivy.xsd, false to force no validation | No. Defaults to default ivy value (as configured in configuration file) |
Suppose we have one dependency called mydep in revision 1.0 publishing two artifacts: foo.jar and bar.jar.
Then:
<artifactproperty conf="build"
name="[module].[artifact]-[revision]"
value="${cache.dir}/[module]/[artifact]-[revision].[ext]"/>
mydep.foo-1.0 = my/cache/dir/mydep/foo-1.0.jar
mydep.bar-1.0 = my/cache/dir/mydep/bar-1.0.jar
The buildlist task enable to obtain a filelist of files (usually build.xml files) ordered according to ivy dependency information from the least dependent to the most one, or the inverse. (since 1.2)
This is particularly useful combined with subant, to build a set of interelated projects being sure that a dependency will be built before any module depending on it.
since 1.3 A root attribute can also be used to include, among all the modules found, only the one that are dependencies (either direct or transitive) of a root module. This can also be used with the excluderoot attribute, which when set to true will exclude the root itself from the list.
Attribute | Description | Required |
---|---|---|
reference | the reference of the filelist to set | Yes |
ivyfilepath | the relative path from files to order to corresponding ivy files | No. Defaults to ${ivy.buildlist.ivyfilepath} |
root | since 1.3 the name of the module which should be considered as the root of the buildlist | No. Defaults to no root (all modules are used in the build list) |
excluderoot | since 1.3 true if the root defined should be excluded from the list | No. Defaults to false |
haltonerror | true to halt the build when an invalid ivy file is encountered, false to continue | No. Defaults to true |
skipbuildwithoutivy | true to skip files of the fileset with no corresponding ivy file, false otherwise. If false the file with no corresponding ivy file will be considered as independent of the other and put at the beginning of the built filelist. | No. Defaults to false |
reverse | true to obtain the list in the reverse order, i.e. from the most dependent to the least one | No. Defaults to default false |
FileSets are used to select sets of files to order.
<ivy:buildlist reference="build-path">
<fileset dir="projects" includes="**/build.xml"/>
</ivy:buildlist>
This list can then be used like that:
<subant target="build" buildpathref="build-path" />
<ivy:buildlist reference="build-path" ivyfilepath="ivy/ivy.xml" reverse="true">
<fileset dir="projects" includes="**/build.xml"/>
</ivy:buildlist>
<ivy:buildlist reference="build-path" ivyfilepath="ivy/ivy.xml" root="myapp">
<fileset dir="projects" includes="**/build.xml"/>
</ivy:buildlist>
Attribute | Description | Required |
---|---|---|
name | the name of the variable to set | No |
value | the value of the variable to set | Yes when using the name attribute |
file | the filename of the property file to load as ivy variables | One of these, when not using the name attribute |
url | the url from which to read ivy variables | |
prefix | Prefix to apply to variables. A "." is appended to the prefix if not specified. | No |
In the case you want to call ivy as a standalone program (outside from ant), you have to put commons-cli 1.0 and its dependencies in your classpath.
Then here is how to call it:
java fr.jayasoft.ivy.Main -?
since 1.3 System properties are included as ivy variables, so you can easily define an ivy variable like this:
java -Dmyivyvar=myvalue fr.jayasoft.ivy.Main [parameters]
java fr.jayasoft.ivy.Main
java fr.jayasoft.ivy.Main -conf path/to/myivyconf.xml -ivy path/to/myivy.xml
java fr.jayasoft.ivy.Main -conf path/to/myivyconf.xml -dependency apache commons-lang 2.0
This is equivalent to:
java fr.jayasoft.ivy.Main -conf path/to/myivyconf.xml -ivy ivy.xml
<ivy-module version="1.0">
<info organisation="org"
module="standalone"
revision="working"
/>
<dependencies>
<dependency org="apache" name="commons-lang" rev="2.0" conf="default->*"/>
</dependencies>
</ivy-module>
java fr.jayasoft.ivy.Main -conf path/to/myivyconf.xml -ivy path/to/myivy.xml -cachepath mycachefile.txt
This section is the home of a bunch of appendixes to ivy main documentation.
For the moment, you will find here a product comparison giving a rapid overview of several dependency management tools and how they compare to ivy.
IvyRep is the official ivy repository. For the moment, it only stores ivy files, artifacts being most of the time found on ibiblio.
You can find more information on ivyrep on its own home page:
http://ivyrep.jayasoft.org/.
We are frequently asked how ivy compares to maven2, and since the products comparison page is really outdated, we have decided that this comparison deserves its own page.
Obviously this comparison is biased (hey, you are on official Ivy site :-)), but we'll try to keep it as fair as possible. Do not hesitate to add comment if you feel something is missing or false on this page. You can also have a look at Maven2 feature comparison page on codehaus, which itself offers another point of view.
But here is the points we think mainly differentiate maven2 and Ivy.
First, the most important difference between maven2 and ivy is that they aren't at all the same kind of tools. Maven2 is a software project management and comprehension tool, whereas Ivy is only a dependency management tool, highly integrated with ant, the popular build management tool. Maven2 offers dependency management facility, and that's why many ask how ivy compares to maven2. That's why we'll focus only on dependency management features of maven2 in this comparison.
So if you look for an out of the box software project management tool, you may skip the rest of this comparison and check what maven2 has to offer.
Ivy heavily relies on a unique concept called configuration. In ivy, module a configuration is a way to use or to see the module. For instance, you can have a test and runtime configuration in your module. But you can also have a mysql and an oracle configuration. Or an hibernate and a jdbc configuration. In each configuration you can declare what artifacts (jar, war, ...) are required. And in each configuration, you can declare your dependencies on other modules, and describe which configuration of the dependency you need. This is called configuration mapping, and it is a very flexible way to answer to a lot of problems we face very often in software development.
Maven2 on its side has something called the scope. You can declare a dependency as being part of the test scope, or the buildtime scope. Then depending on this scope you will get the dependency artifact (only one artifact per module in maven2) with its dependencies depending on their scope. Scopes are predefined in maven2 and you can't change that. No way to create an oracle scope. No way to indicate you need what as been declared to be needed in the runtime scope of your dependency in your compile one. Everything here is written in the marble.
And this leads to some kind of troubles... as Matt Raible stated in his blog talking about maven2 dependencies:
[quote]
There are a *lot* of unnecessary dependencies downloaded for many libraries. For example, Hibernate downloads a bunch of JBoss JARs and the Display Tag downloads all the various web framework JARs. I found myself excluding almost as many dependencies as I added.
[/quote]
The problem is that hibernate can be used with several cache implementations, several connection pool implementation, ... And this can't be managed with scopes, wheres Ivy configurations offers an elegant solution to this kind of problem. For instance, in ivy, assuming hibernate as an ivy file like this one, then you can declare a dependency like that:
<dependency org="hibernate" name="hibernate" rev="2.1.8" conf="default->proxool,oscache"/>
<dependency org="hibernate" name="hibernate" rev="2.1.8" conf="default->dbcp,swarmcache"/>
An important thing to be able to use a tool is its amount of documentation. With Ivy, even if they are written in broken english (would you have prefered well written french :-)), the printer friendly version of the documentation is now about 120 pages.
With maven2, it's a bit difficult to clearly know what can be considered as dependency management documentation, but we didn't managed to find much: some small introductory guides, short entries in the pom reference guide, and not really much more.
Conflict management are an important part of dependency management, cause when dealing with transitive dependencies you often have to face conflicts. In this area, Ivy let you do whatever you want: use one conflict manager in one module, another one elsewhere, decide which revision you will get, ... You can even plug your own conflict manager if you need to.
With maven2, conflict management is quite simple: the principle is to get the nearest definition. So if your module depends on foo 1.0, none of your dependencies will ever manage to get foo 1.1 without a change in your own dependency declaration. It may be ok in some cases, it may not in others...
In ivy many things can be configured, and many others can be plugged in: dependency resolvers, conflict manager, module descriptor parser, latest revision strategy, ... Maven2 also offers repository pluggability, but not much more as far as we know. Moreover, repository configuration seems to be less flexible than with ivy.
Maven2 comes out of the box wonfigured to use ibiblio maven2 repository, which contains a lot of modules (both artifacts and module descriptors). The only problem some may face is that module descriptors are not always checked, so some are not really well written.
Ivy, on its side, is used out of the box with ivyrep, ivy official repository, which contains only a few modules, and is not updated frequently. But it is also compatible with maven1 ibiblio repository (for artifacts only, no module descriptors), can also be used with maven2 repository (with pom compatibility, you will here only face some naming problems that can be addressed using the namespace feature, and you won't benefit from ivy configurations with the module descriptors found there), and also has an ivyrep sandbox in which much more module descriptors can be found (not checked, as with ibiblio repository).
Product | Maven ibiblio compatibility |
Ant integration |
Continuous integration |
Transitive dependencies |
Flexibility | Maturity | License |
---|---|---|---|---|---|---|---|
Ivy | ++ | ++ | ++ | +++ | ++ | ++ | BSD |
Maven | +++ | -- | + | -- | + | +++ | Apache Software License |
Maven2 | ++ * | - | ++ | + | + | --- | Apache Software License |
HttpUnit Dependencies | ++ | ++ | + | -- | + | - | MIT License |
Savant | -- | ++ | -- | + | ++ | ++ | Other |