Ivy: Overview
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against Apache Ivy 2.6.0 (announced on 15 July 2026) running inside Apache Ant 1.10.18. Every example marked as
run was executed on JDK 26 on 2026-10-16, on macOS, in a scratch directory with its own Ivy cache; output that comes from a run is
shown as printed, with the long scratch path shortened to <scratch>, the home directory to <home> and the machine name to <host>.
Anything that could not be run here is labelled "not run here". The commands use a POSIX shell.
Ant has no idea what a dependency is. It compiles, copies and packages whatever sits in directories you name, and the JARs those
directories need have to get there some other way: checked into version control, copied by hand, or fetched by a get task from a
fixed URL. Ivy is the answer the Ant project itself gives to that gap. It is a dependency manager that runs inside Ant (and also
on its own from the command line): given a description of what a module needs, it finds those modules in one or more repositories,
follows their own dependencies, decides which revision wins when two parts of the graph disagree, downloads the files into a local
cache and hands them to the build as a classpath or a directory of JARs. This page is the first of six on Ivy. It covers what Ivy is,
how it is installed, and a complete first run; the other five go deep on each part, and are linked where they apply:
module descriptors and configurations,
settings and resolvers,
conflicts and versions,
the Ant tasks and
publishing and multi-project builds.
The other Ant dependency tool, the Resolver Ant Tasks that wrap Maven’s own resolver, has its own page:
Maven Resolver Ant Tasks. The language-neutral ideas
(coordinates, scopes, transitivity, mediation) are in
Dependency Management Fundamentals. The running scenario
(tidepool) is described on the section landing page.
What Ivy is, and its status
Ivy describes itself as a tool for managing (recording, tracking, resolving and reporting) project dependencies, characterized by flexibility and configurability and by tight integration with Ant. Three properties follow from that and shape everything else:
-
It is process agnostic. Nothing in Ivy says where files live, how modules are named in a repository, or what a build looks like. Those are settings you provide (or accept from the default settings that ship inside the JAR, which look like Maven Central).
-
It reads Maven metadata. A POM in a repository is a module descriptor to Ivy, so the whole of Maven Central is usable without any conversion. That is what makes the first example below work with no repository configuration at all.
-
Its model is richer than Maven’s scopes. A module can define any number of named configurations (views of itself), and every dependency says which configuration of the other module it needs in which of its own. That is the subject of the next page; this page only introduces the word.
As of the date of this page Ivy is an active subproject of Apache Ant, not in the Attic, and 2.6.0 is the current release. The facts worth knowing before adopting it:
-
Java. Ivy 2.6.0 needs Java 8 or later (the compatibility page gives the floors of every line, reproduced in the table below). Ivy does not require any particular Ant version beyond one that runs on that Java.
-
Not thread-safe. The compatibility page states that Ivy does not support multithreaded use and so should not be used with the Ant
<parallel>task. Parallel builds that each run Ivy in a separate JVM are fine; two Ivy resolves inside one JVM are not. -
IvyDE is archived. The Eclipse plugin, IvyDE, was archived by an Ant PMC vote: its home page says all resources are read only and no further development will be done. Ivy itself is unaffected. IDE support for Ivy-managed projects today means importing the resolved JARs, as the CI & IDE Integration page describes.
-
Security. The 2.6.0 release fixes CVE-2026-26032, a path traversal in the PackagerResolver, reachable only by someone able to add coordinates containing
../to a packager repository. The release notes also say that if you resolved with a version before 2.6.0, you may need to remove your Ivy cache for some of the fixes to take effect. Earlier advisories (CVE-2022-37865, CVE-2022-37866, CVE-2022-46751) are listed on the same security page. -
A new conflict manager. 2.6.0 added
nearest, which resolves conflicts the way Maven does. The default stayslatest-revision. Conflicts are the subject of their own page.
Source: Apache Ivy: home page
Source: Apache Ivy: Security
Source: Apache IvyDE: home page
Release history
Ivy was created at Jayasoft and donated to the ASF: the software grant was received on 7 November 2006, the first Apache release (2.0.0-alpha1-incubating) came out on 26 April 2007, and Ivy graduated as a subproject of Ant in October 2007. The documentation you read for 2.x was migrated from the old Jayasoft site. The table lists the final releases; each line also had release candidates (for instance 2.5.0-rc1 in April 2018) that are not listed.
| Release | Announced | What matters |
|---|---|---|
2.0.0 |
2009-01-20 |
First final 2.x. Settings files renamed from |
2.1.0 |
2009-10-08 |
Final release of the 2.1 line (release candidates in March and July 2009). |
2.2.0 |
2010-09-30 |
|
2.3.0 |
2013-01-21 |
Last line that runs on Java 1.4. |
2.4.0 |
2014-12-26 |
Needs Java 5. |
2.5.0 |
2019-10-24 |
Needs Java 7; attributes inherited through |
2.5.1 |
2022-11-04 |
Needs Java 8. Fixes CVE-2022-37865 and CVE-2022-37866 (file creation and path traversal). |
2.5.2 |
2023-08-20 |
Fixes CVE-2022-46751 (XML external entity injection). |
2.5.3 |
2024-12-23 |
No security fix listed on the security page. |
2.6.0 |
2026-07-15 |
|
The "what matters" column is taken from the reference pages (their "since 2.x" remarks), the 2.6.0 release notes and the security
page, all cited under the tables. The Maven Central listing of
org.apache.ivy:ivy has exactly these versions plus the 2.0.0 betas and the release candidates, with 2.6.0 as latest and
release.
| Ivy line | Minimum Java to run it |
|---|---|
up to 2.3.x |
Java 1.4 |
2.4.0 |
Java 5 |
2.5.0 |
Java 7 |
2.5.1 and later, including 2.6.0 |
Java 8 |
Ivy 2.6.0 has no Java ceiling documented; it ran on JDK 26 for every example on this page. Which JDK your builds target is a
different question and is decided by the javac task, as the Compiling Java page
explains.
Terminology
Ivy has a small vocabulary and uses it strictly; the reference pages and every error message assume it. The table maps each word to its Maven and Gradle counterpart, because that is the translation you will do in your head most often.
| Ivy term | Meaning | Maven | Gradle |
|---|---|---|---|
organisation |
The group that produces a module (flat name, usually an inverted domain). |
|
group |
module |
A reusable unit with a chain of revisions. |
|
name |
revision |
One delivered state of a module: release, milestone, integration build. |
|
version |
branch |
A line of development of a module; the trunk is also a branch. Optional. |
none |
none |
status |
How stable a revision is: |
none (the |
|
module descriptor |
The file that identifies a revision and lists its artifacts, configurations and dependencies: |
|
|
artifact |
One file published with a revision (a JAR, a source ZIP, a signature). |
artifact (type and classifier) |
artifact (type and classifier) |
type, extension |
The purpose of an artifact ( |
type ( |
type, extension and classifier |
configuration |
A view of a module: a named set of artifacts and dependencies for one way of using or building it. |
scope (a fixed list) |
configuration, variant |
settings |
The |
|
|
repository |
A location holding descriptors and artifacts, reached by a resolver. |
repository |
repository |
Ivy writes a module coordinate as organisation#module;revision, which is what you see in every log line
(io.tidepool#tidepool-engine;1.0.0). Maven writes the same thing as groupId:artifactId:version. In Ivy the pieces after the
revision (branch, artifact type, extension) are separate attributes, not part of the coordinate string. The cross-tool table in
Comparing Ant, Maven & Gradle adds the rest of the mapping.
Two differences from Maven are worth stating now because they surprise people. First, a dependency in Ivy is on a module, never on
an artifact: you ask for commons-csv;1.14.1 and a mapping between configurations decides which of its files you get (the
next page shows how that goes wrong with the
default mapping). Second, the status of a revision is a first-class value that dynamic revisions such as latest.release use to
choose; Maven has no counterpart.
Source: Ivy documentation: Terminology
The principle: configure, resolve, retrieve, report, publish
Every use of Ivy is one or more of five steps. They are the same whether you drive them from Ant tasks, as this page does, or from the command line.
-
Configure. Ivy needs a set of dependency resolvers, each able to find descriptors and artifacts given organisation, module, revision, artifact name, type and extension, and a rule saying which resolver serves which module. That is the settings file. When you give none, Ivy uses a built-in default that points an
ibiblioresolver at Maven Central (details below). The settings and resolvers page covers everything you can put there. -
Resolve. The resolve is the moment Ivy actually works out the dependencies of one module. It reads the module’s
ivy.xml, asks the resolvers for each dependency’s descriptor, goes through the transitive graph depth first, applies conflict management while it goes so that a losing branch is never downloaded, and finally downloads the artifacts of the winners into the cache. It then writes an XML report per configuration, so that later steps do not walk the graph again. Resolve is also where dynamic revisions such as1.+become fixed ones. -
Retrieve. Copy the resolved artifacts from the cache into a directory structure you choose with a pattern such as
build/lib/[conf]/[artifact]-[revision].[ext]. -
Build a path from the cache. Instead of copying, use the files where they are:
cachepathturns the resolve report into an Ant path. This is what you want for compiling, and what IDE integrations do.cachefilesetdoes the same as a fileset. -
Report. An XSL transformation of the resolve report gives an HTML page (and a GraphML file for graph tools) of who needed what.
-
Publish. Deliver a version of your own module, a resolved
ivy.xmlplus its artifacts, into a repository so others can depend on it. That is the subject of the publishing page; the dashed arrow in the figure marks that it is a separate step that starts from the same module, not part of a dependency resolve.
Installing Ivy
Ivy is one JAR, ivy-2.6.0.jar, 1,413,973 bytes, 889 entries, published as org.apache.ivy:ivy:2.6.0 on Maven Central. Its
only job at install time is to be on Ant’s classpath so that the antlib:org.apache.ivy.ant tasks exist. The JAR has optional
dependencies, such as Apache HttpClient and Jsch (the compatibility page names both) and Commons Compress for pack200 (the 2.6.0
release notes); their versions are in Ivy’s own descriptor, and you add them only when you use the feature that needs them.
Getting the JAR from Maven Central
mkdir -p lib
curl -fsSL -o lib/ivy-2.6.0.jar https://repo1.maven.org/maven2/org/apache/ivy/ivy/2.6.0/ivy-2.6.0.jar
curl -fsSL https://repo1.maven.org/maven2/org/apache/ivy/ivy/2.6.0/ivy-2.6.0.jar.sha1
shasum -a 1 lib/ivy-2.6.0.jar
Run here, the two digests are the same:
11a76d2e1d439170c61b47a7a13110a78c6c0824
11a76d2e1d439170c61b47a7a13110a78c6c0824 lib/ivy-2.6.0.jar
Central also serves an .asc PGP signature next to the JAR (it answers HTTP 200); checking it needs the Apache KEYS file and is not
run here. The Ivy download page offers three distributions, each as a ZIP and a tar.gz with a PGP signature, a SHA-512 digest and a CycloneDX SBOM:
bin, bin-with-deps (which adds the optional dependencies) and src. For a build you only need the JAR. The manual installation
the documentation describes is "copy the JAR into ANT_HOME/lib", which works but ties every build on the machine to one Ivy
version. The three ways below keep the version in the project instead.
Source: Ivy documentation: Installation
Source: Apache Ivy: Download
Three ways to put the tasks on Ant’s classpath
| Way | How | Use it when |
|---|---|---|
|
|
One-off runs, CI jobs, and a quick check. The version is explicit in the command. |
|
Copy the JAR as |
A developer machine where every project uses the same Ivy. Not reproducible across machines. |
|
|
A build file that must work from a fresh checkout, with the Ivy version stated in the file. |
In all three the build file declares the namespace on its root element and then writes every task with the ivy: prefix:
<project name="tidepool-engine" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
antlib:org.apache.ivy.ant is the Antlib URI: Ant looks for a resource named org/apache/ivy/ant/antlib.xml on its classpath, and
the Ivy JAR contains one. Inside it are the declarations of the tasks and types, which is the quickest authoritative list of what
the namespace holds:
settings, resources (types)
configure, resolve, retrieve, deliver, publish, extract, cachepath, cachefileset,
report, repreport, var, check, artifactproperty, buildlist, install, convertpom,
makepom, artifactreport, info, addpath, listmodules, findrevision, buildnumber,
cleancache, buildobr, convertmanifest, fixdeps, dependencytree, checkdepsupdate
workspaceresolver (type)
That listing was read from the JAR (unzip -p lib/ivy-2.6.0.jar org/apache/ivy/ant/antlib.xml) and condensed to one line per group; the
task pages are in
Ivy Ant Tasks. How Ant treats Antlib URIs in general, and how to declare your
own, is in Antlibs & Namespaces.
If the tasks are not on the classpath, the first ivy: task fails, and the message tells you where Ant looked:
Buildfile: <scratch>/c/build.xml
resolve:
BUILD FAILED
<scratch>/c/build.xml:3: Problem: failed to create task or type antlib:org.apache.ivy.ant:resolve
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any <presetdef>/<macrodef> declarations have taken place.
No types or tasks have been defined in this namespace yet
This appears to be an antlib declaration.
Action: Check that the implementing library exists in one of:
-<scratch>/tools/apache-ant-1.10.18/lib
-<home>/.ant/lib
-a directory added on the command line with the -lib argument
Total time: 0 seconds
This is by far the most common Ivy installation problem, and the three directories in the message are exactly the three ways above.
Source: Ivy documentation: Installation
Source: Ant manual: Antlib
Letting the build file fetch Ivy
The documentation’s "automatic" installation is a self-contained snippet: download the JAR once into a directory under the user’s
home, then taskdef from there. Its pinned version in the documentation is 2.5.0, which is out of date; below it is set to 2.6.0.
This is the complete build file used for the compile example later on this page, so it is shown whole:
<project name="tidepool-engine" default="compile" xmlns:ivy="antlib:org.apache.ivy.ant">
<property name="ivy.install.version" value="2.6.0"/>
<condition property="ivy.home" value="${env.IVY_HOME}">
<isset property="env.IVY_HOME"/>
</condition>
<property name="ivy.home" value="${user.home}/.ant"/>
<property name="ivy.jar.dir" value="${ivy.home}/lib"/>
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar"/>
<target name="download-ivy" unless="offline">
<mkdir dir="${ivy.jar.dir}"/>
<get src="https://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>
<target name="init-ivy" depends="download-ivy">
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
<target name="resolve" depends="init-ivy" description="resolve the dependencies">
<ivy:resolve/>
</target>
<target name="compile" depends="resolve" description="compile the model and the engine">
<ivy:cachepath pathid="compile.classpath" conf="compile"/>
<mkdir dir="build/classes"/>
<javac destdir="build/classes" release="21" includeantruntime="false" classpathref="compile.classpath">
<src path="src/model"/>
<src path="src/engine"/>
</javac>
<pathconvert property="cp.names" refid="compile.classpath" pathsep=" ">
<mapper type="flatten"/>
</pathconvert>
<echo message="compiled against: ${cp.names}"/>
</target>
<target name="report" depends="resolve" description="write the HTML resolve reports">
<ivy:report todir="build/report"/>
</target>
</project>
How it works, line by line: ivy.home is IVY_HOME if that environment variable is set and <home>/.ant otherwise (the condition
sets it only when the variable exists, and the later property is then ignored because properties are immutable). download-ivy
fetches the JAR with get and usetimestamp, so it is downloaded again only when Maven Central has a newer file; -Doffline=true
skips it through unless. init-ivy builds a path from every JAR in that directory and taskdef`s the Antlib resource under the
Antlib URI. Because `<home>/.ant/lib is also one of the directories Ant puts on its own classpath, a JAR downloaded by the first run
is picked up automatically by later runs; the explicit taskdef is what makes the first run work. For the run below the
property ivy.home was set on the command line to a directory inside the scratch area, so that nothing is written outside it. The
source tree is the tidepool model and engine source copied into src/model and src/engine; the ivy.xml is the one in the
next section.
$ ant -Divy.home=<scratch>/ivyhome
Buildfile: <scratch>/b/build.xml
download-ivy:
[mkdir] Created dir: <scratch>/ivyhome/lib
[get] Getting: https://repo1.maven.org/maven2/org/apache/ivy/ivy/2.6.0/ivy-2.6.0.jar
[get] To: <scratch>/ivyhome/lib/ivy.jar
init-ivy:
resolve:
[ivy:resolve] :: Apache Ivy 2.6.0 - 20260712075753 :: https://ant.apache.org/ivy/ ::
[ivy:resolve] :: loading settings :: url = jar:file:<scratch>/ivyhome/lib/ivy.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:resolve] :: resolving dependencies :: io.tidepool#tidepool-engine;1.0.0
[ivy:resolve] confs: [compile, runtime]
[ivy:resolve] found org.apache.commons#commons-csv;1.14.1 in public
[ivy:resolve] found commons-io#commons-io;2.20.0 in public
[ivy:resolve] found commons-codec#commons-codec;1.19.0 in public
[ivy:resolve] :: resolution report :: resolve 42ms :: artifacts dl 2ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| compile | 3 | 0 | 0 | 0 || 3 | 0 |
| runtime | 3 | 0 | 0 | 0 || 3 | 0 |
---------------------------------------------------------------------
compile:
[mkdir] Created dir: <scratch>/b/build/classes
[javac] Compiling 6 source files to <scratch>/b/build/classes
[echo] compiled against: commons-csv-1.14.1.jar commons-io-2.20.0.jar commons-codec-1.19.0.jar
BUILD SUCCESSFUL
Total time: 0 seconds
(The Ivy cache was already warm from the example in the next section, which is why the resolution report shows nothing downloaded. A
cold run is shown there.) Ivy printed its version and build stamp (2.6.0 - 20260712075753, the time the JAR was built) and then
loaded the settings from inside its own JAR, which is the built-in default. The javac compiled six files against the three JARs
Ivy had put on the path. report turns the resolution into HTML:
report:
[ivy:report] Processing <scratch>/ivyuser/cache/io.tidepool-tidepool-engine-compile.xml to <scratch>/b/build/report/io.tidepool-tidepool-engine-compile.html
[ivy:report] Processing <scratch>/ivyuser/cache/io.tidepool-tidepool-engine-runtime.xml to <scratch>/b/build/report/io.tidepool-tidepool-engine-runtime.html
[ivy:report] Processing <scratch>/ivyuser/cache/io.tidepool-tidepool-engine-compile.xml to <scratch>/b/build/report/io.tidepool-tidepool-engine-compile.graphml
[ivy:report] Processing <scratch>/ivyuser/cache/io.tidepool-tidepool-engine-runtime.xml to <scratch>/b/build/report/io.tidepool-tidepool-engine-runtime.graphml
The .html files open in a browser (with ivy-report.css next to them); the .graphml files open in a graph editor such as yEd.
Both are generated from the per-configuration XML files that resolve wrote into the cache, which are shown below.
Source: Ant manual: Get
Running Ivy without Ant
The JAR also has a main class, so Ivy can resolve a descriptor without any build file. It is useful to check a descriptor or to
print a version:
$ java -cp lib/ivy-2.6.0.jar org.apache.ivy.Main -version
Apache Ivy 2.6.0 - 20260712075753 :: https://ant.apache.org/ivy/
$ java -Divy.default.ivy.user.dir=<scratch>/ivyuser -jar lib/ivy-2.6.0.jar -ivy a/ivy.xml -confs compile
:: loading settings :: url = jar:file:<scratch>/lib/ivy-2.6.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
:: resolving dependencies :: io.tidepool#tidepool-engine;1.0.0
confs: [compile]
found org.apache.commons#commons-csv;1.14.1 in public
found commons-io#commons-io;2.20.0 in public
found commons-codec#commons-codec;1.19.0 in public
:: resolution report :: resolve 53ms :: artifacts dl 2ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| compile | 3 | 0 | 0 | 0 || 3 | 0 |
---------------------------------------------------------------------
The rest of this page stays with Ant, because the point of Ivy on this site is to give Ant builds dependency management.
Source: Ivy documentation: Standalone
A first resolve and retrieve
The smallest useful Ivy project is two files. ivy.xml says what the tidepool engine module needs; build.xml runs resolve and
retrieve.
<ivy-module version="2.0">
<info organisation="io.tidepool" module="tidepool-engine" revision="1.0.0"/>
<configurations>
<conf name="compile" description="needed to compile"/>
<conf name="runtime" extends="compile" description="needed to run"/>
</configurations>
<dependencies>
<dependency org="org.apache.commons" name="commons-csv" rev="1.14.1" conf="compile->default"/>
</dependencies>
</ivy-module>
<project name="tidepool-engine" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="resolve" description="resolve and retrieve the dependencies">
<ivy:resolve/>
<ivy:retrieve pattern="build/lib/[conf]/[artifact]-[revision].[ext]"/>
</target>
</project>
Reading ivy.xml: info identifies the module (organisation, module, revision). configurations declares two views of it;
runtime extends compile, which means everything required in compile is also required in runtime. The one dependency is
commons-csv at an exact revision, and conf="compile->default" reads "in my compile configuration I need the default
configuration of that module". Because the Maven POM of commons-csv is converted to Ivy configurations on the fly, default there
means its own JAR plus its runtime dependencies. The ivy:resolve task with no attributes reads ivy.xml from the project
directory, and ivy:retrieve copies into the pattern, where [conf], [artifact], [revision] and [ext] are tokens
Ivy replaces. The next page,
Ivy: Module Descriptors & Configurations,
explains every part of that file.
The first run, with an empty cache, using the JAR from -lib:
$ ant -lib lib/ivy-2.6.0.jar
Buildfile: <scratch>/a/build.xml
resolve:
[ivy:resolve] :: Apache Ivy 2.6.0 - 20260712075753 :: https://ant.apache.org/ivy/ ::
[ivy:resolve] :: loading settings :: url = jar:file:<scratch>/lib/ivy-2.6.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:resolve] :: resolving dependencies :: io.tidepool#tidepool-engine;1.0.0
[ivy:resolve] confs: [compile, runtime]
[ivy:resolve] found org.apache.commons#commons-csv;1.14.1 in public
[ivy:resolve] found commons-io#commons-io;2.20.0 in public
[ivy:resolve] found commons-codec#commons-codec;1.19.0 in public
[ivy:resolve] downloading https://repo1.maven.org/maven2/org/apache/commons/commons-csv/1.14.1/commons-csv-1.14.1.jar ...
[ivy:resolve] ............... (59kB)
[ivy:resolve] .. (0kB)
[ivy:resolve] [SUCCESSFUL ] org.apache.commons#commons-csv;1.14.1!commons-csv.jar (123ms)
[ivy:resolve] downloading https://repo1.maven.org/maven2/commons-io/commons-io/2.20.0/commons-io-2.20.0.jar ...
[ivy:resolve] ...................................... (550kB)
[ivy:resolve] .. (0kB)
[ivy:resolve] [SUCCESSFUL ] commons-io#commons-io;2.20.0!commons-io.jar (166ms)
[ivy:resolve] downloading https://repo1.maven.org/maven2/commons-codec/commons-codec/1.19.0/commons-codec-1.19.0.jar ...
[ivy:resolve] ........................ (365kB)
[ivy:resolve] .. (0kB)
[ivy:resolve] [SUCCESSFUL ] commons-codec#commons-codec;1.19.0!commons-codec.jar (125ms)
[ivy:resolve] :: resolution report :: resolve 1563ms :: artifacts dl 419ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| compile | 3 | 3 | 3 | 0 || 3 | 3 |
| runtime | 3 | 3 | 3 | 0 || 3 | 3 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: io.tidepool#tidepool-engine
[ivy:retrieve] confs: [compile, runtime]
[ivy:retrieve] 6 artifacts copied, 0 already retrieved (1952kB/5ms)
BUILD SUCCESSFUL
Total time: 2 seconds
Reading the output, in order:
-
loading settings :: url = jar:file:...!/org/apache/ivy/core/settings/ivysettings.xmlmeans no settings were configured, so Ivy loaded its built-in default from inside the JAR. When a project has its ownivysettings.xmlthis line saysfile = ...instead. -
resolving dependencies :: io.tidepool#tidepool-engine;1.0.0andconfs: [compile, runtime]: the module and the configurations being resolved. With noconfattribute,resolvetakes every configuration. -
found ... in public: for each module in the graph, the descriptor was found by the resolver namedpublic, which is theibiblioresolver for Maven Central in the default settings. There are threefoundlines for one declared dependency: commons-csv brought in commons-io and commons-codec. -
downloading ...followed by dots and a size: the artifact download, one dot per chunk. Only now, after the whole graph and the conflict decisions, does Ivy download JARs. The descriptor (the POM) of each module was fetched during thefoundstep, and the parent POMs and BOM imports it needed were fetched silently (they are visible in the cache listing below). -
The resolution report. One row per configuration.
modules numberis how many modules are in that configuration;searchhow many required a repository lookup;dwnldedhow many descriptors or artifacts were downloaded;evictedhow many lost a conflict;artifacts numberanddwnldedthe files. Both configurations have three modules becauseruntimeextendscompile. -
retrieve: six artifacts were copied, three modules for each of the two configurations.
The second run changes only the report; nothing is downloaded and retrieve finds the files already in place:
[ivy:resolve] :: resolution report :: resolve 43ms :: artifacts dl 2ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| compile | 3 | 0 | 0 | 0 || 3 | 0 |
| runtime | 3 | 0 | 0 | 0 || 3 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: io.tidepool#tidepool-engine
[ivy:retrieve] confs: [compile, runtime]
[ivy:retrieve] 0 artifacts copied, 6 already retrieved (0kB/2ms)
Only the resolve and retrieve lines of the second run are shown; the banner and found lines are the same as before. That
speed (43 ms instead of 1.5 s) is the cache. Ivy assumes by default that a revision never changes, so once it has a descriptor and
its artifacts in the cache it does not query the repository at all. The exceptions (dynamic revisions, changing revisions, resolvers
with checkmodified) are on the
conflicts and versions page.
What retrieve created, with the pattern build/lib/[conf]/[artifact]-[revision].[ext]:
build/lib/compile/commons-codec-1.19.0.jar
build/lib/compile/commons-csv-1.14.1.jar
build/lib/compile/commons-io-2.20.0.jar
build/lib/runtime/commons-codec-1.19.0.jar
build/lib/runtime/commons-csv-1.14.1.jar
build/lib/runtime/commons-io-2.20.0.jar
Each configuration has its own copy of its files, which is the point of the [conf] token: the application’s runtime directory
and the compile classpath can differ. Retrieve also supports sync="true" (delete files in the target that are not part of the
retrieve), symbolic links, and, new in 2.6.0, override children that change the revision of a transitive dependency when the task does its
own resolve from nested dependency elements (shown on the next page). Those options are in
Ivy Ant Tasks.
Source: Ivy documentation: ivy:resolve
Source: Ivy documentation: ivy:retrieve
Source: Ivy tutorial: Quick Start
What the default settings do
The default configuration is not a single resolver. It is five small files inside the JAR that are included in turn, and reading them
explains the word public in the log and where local and shared come from. This is their content, read from the 2.6.0 JAR:
<ivysettings>
<settings defaultResolver="default"/>
<include url="${ivy.default.settings.dir}/ivysettings-public.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-shared.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-local.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-main-chain.xml"/>
<include url="${ivy.default.settings.dir}/ivysettings-default-chain.xml"/>
</ivysettings>
<ivysettings>
<resolvers>
<ibiblio name="public" m2compatible="true"/>
</resolvers>
</ivysettings>
The other files define a filesystem resolver shared rooted at ${ivy.default.ivy.user.dir}/shared, a filesystem resolver local
rooted at ${ivy.default.ivy.user.dir}/local, a chain named main with dual="true" that tries shared then public, and a
chain named default with returnFirst="true" and checkmodified="true" that tries local then main. So, in plain words, a
dependency is looked up in the local repository (the repository the Ivy tutorials publish to, a rough counterpart of Maven’s
local repository for your own builds), then in a shared file repository, then in Maven Central, and the first hit wins. The ibiblio resolver with no root
attribute points at Maven Central, as the principle page says. That is the whole reason a descriptor with a Maven coordinate works
with no settings.
ivy.default.ivy.user.dir is the variable that points at the Ivy home directory; unless set it is .ivy2 in the user’s home directory
(confirmed here by running with a different user.home, which created .ivy2/cache under it).
The cache is in its cache subdirectory. All the examples on these pages set -Divy.default.ivy.user.dir=<scratch>/ivyuser on the
command line, because Ant properties are imported as Ivy variables, so that nothing was written to the real ~/.ivy2 and the
examples start from a known cache. That variable is used by the default settings but is not described on the settings reference page;
treat setting it from the command line as a convenience, not a contract. For a project you would write your own settings file
(and set the cache there with the caches element). The
settings and resolvers page covers that.
Source: Ivy documentation: caches
The Ivy cache
Ivy’s cache has two parts, and the difference matters for sharing it and for cleaning it:
-
The repository cache holds what was downloaded from repositories, with a small properties file per module recording where each file came from. It can be shared between machines or users if you pick a suitable lock strategy.
-
The resolution cache holds the results of resolves, so that
retrieve,cachepathandreportcan reuse them. It is overwritten by every resolve and must never be used by two processes at once.
The default location for both is .ivy2/cache in the user’s home directory. After the first run above, the cache directory
contained (the .original copies of each descriptor and the report stylesheets omitted):
cache/commons-codec/commons-codec/ivy-1.19.0.xml
cache/commons-codec/commons-codec/ivydata-1.19.0.properties
cache/commons-codec/commons-codec/jars/commons-codec-1.19.0.jar
cache/commons-io/commons-io/ivy-2.20.0.xml
cache/commons-io/commons-io/ivydata-2.20.0.properties
cache/commons-io/commons-io/jars/commons-io-2.20.0.jar
cache/io.tidepool-tidepool-engine-compile.xml
cache/io.tidepool-tidepool-engine-runtime.xml
cache/org.apache.commons/commons-csv/ivy-1.14.1.xml
cache/org.apache.commons/commons-csv/ivydata-1.14.1.properties
cache/org.apache.commons/commons-csv/jars/commons-csv-1.14.1.jar
cache/org.apache.commons/commons-parent/ivy-85.xml
cache/org.apache.commons/commons-parent/ivydata-85.properties
cache/org.apache/apache/ivy-35.xml
cache/org.apache/apache/ivydata-35.properties
cache/org.junit/junit-bom/ivy-5.13.1.xml
cache/org.junit/junit-bom/ivydata-5.13.1.properties
cache/resolved-io.tidepool-tidepool-engine-1.0.0.properties
cache/resolved-io.tidepool-tidepool-engine-1.0.0.xml
How to read it:
-
cache/<organisation>/<module>/is the repository cache, one directory per module. Inside it,ivy-<revision>.xmlis the module descriptor converted to Ivy format (for a module whose original is a POM, the POM is kept beside it asivy-<revision>.xml.original),ivydata-<revision>.propertiesrecords which resolver found it and the original location of each file, andjars/<name>-<revision>.jaris the artifact. The directory under the module is the artifact type with ansadded, from the default cache pattern[organisation]/[module](/[branch])/[type]s/[artifact]-[revision](-[classifier])(.[ext])(no branch here, so that part is dropped), so asourceartifact would go insourcesand abundleinbundles. -
commons-parent,apacheandjunit-bomwere not asked for by the project. They are the parent POM and the BOM that the commons-csv POM refers to; Ivy had to read them to compute the effective POM, which is why a Maven module can pull more descriptors than artifacts. They have nojarsdirectory. -
io.tidepool-tidepool-engine-compile.xmland-runtime.xmlare the resolution cache: one XML report per module and configuration, named<organisation>-<module>-<conf>.xml. These are the filesretrieve,cachepathandreportread. The tworesolved-...files record the outcome of the resolve for the module itself: the revision each dependency was mapped to, and the module’s descriptor as resolved.
The ivydata file for commons-csv shows the bookkeeping, and why the resolver is named in the logs:
#ivy cached data file for org.apache.commons#commons-csv;1.14.1
artifact.resolver=main
...
artifact\:commons-csv\#jar\#jar\#1409887496.location=https\://repo1.maven.org/maven2/org/apache/commons/commons-csv/1.14.1/commons-csv-1.14.1.jar
...
resolver=public
The converted descriptor in the cache is what a POM looks like to Ivy, including the configurations Ivy invents for Maven scopes. A
fragment (the Maven properties and the long lists of overrides are elided), read from ivy-1.14.1.xml in the cache:
<configurations>
<conf name="default" visibility="public" description="runtime dependencies and master artifact can be used with this conf" extends="runtime,master"/>
<conf name="master" visibility="public" description="contains only the artifact published by this module itself, with no transitive dependencies"/>
<conf name="compile" visibility="public" .../>
<conf name="provided" visibility="public" .../>
<conf name="runtime" visibility="public" .../>
<conf name="test" visibility="public" .../>
...
</configurations>
<publications>
<artifact name="commons-csv" type="jar" ext="jar" conf="master"/>
<artifact name="commons-csv" type="source" ext="jar" conf="sources" m:classifier="sources"/>
<artifact name="commons-csv" type="javadoc" ext="jar" conf="javadoc" m:classifier="javadoc"/>
</publications>
That conversion is the key to using Maven Central from Ivy, and to the traps in it, and it is worked through on the next page. It is also why the cache is not a Maven repository layout and cannot be used by Maven or Gradle directly; the three tools' caches are compared in Repositories & Publishing Across Tools.
To start over, delete the cache directory, or run the cleancache task (see
Ivy Ant Tasks). The release notes of 2.6.0 recommend this after upgrading from an older Ivy, because
some fixes only apply to descriptors parsed afresh.
Source: Ivy documentation: caches
Ivy and the other tools
Ivy answers the same question as Maven’s dependency mechanism and Gradle’s dependency resolution, with a different split of responsibilities. The Apache Ivy project has its own comparison page with Maven; the table puts its points next to what is known on this site for the other two tools.
| Topic | Ivy | Maven | Gradle |
|---|---|---|---|
What it is |
A dependency manager used from Ant (or alone). It does not build. |
A build tool whose model includes dependency management. |
A build tool whose model includes dependency management. |
Descriptor |
|
|
The build script, plus Gradle Module Metadata published for consumers. |
Dependency views |
Any number of named configurations, mapped between modules. |
A fixed list of scopes. |
Configurations and variant-aware resolution. |
Default conflict rule |
|
Nearest definition wins. |
Highest version wins; rich constraints. |
Repositories |
Pluggable resolvers, chains, dual metadata and artifact locations, |
Repositories and mirrors, one layout. |
Repositories (Maven, Ivy, flat directory) with content filtering. |
Local store |
|
|
|
Reads Maven Central |
Yes, through |
Yes. |
Yes. |
Locking and verification |
None built in beyond what a resolver or checksum setting gives. |
|
Lockfiles and verification metadata. |
Three points from the Ivy side of the comparison are still true, and one is not. Still true: Ivy is far more configurable, since
resolvers, conflict managers, version matchers and parsers are all plug-in points, and it can split metadata and artifacts into
different repositories; the Maven comparison page notes that Maven has no repository chaining. Still true: Ivy’s reference
documentation is extensive and covers every feature with examples. No longer true as stated: the comparison page says that in Maven
"none of your dependencies will ever manage to get foo 1.1" without a change in your own declaration, as if that were a limitation.
That is Maven’s nearest-wins rule, which Ivy can now apply itself with the nearest conflict manager, and which Maven has long
complemented with dependencyManagement and BOMs
(Maven dependencies, scopes and mediation). Gradle can also consume Ivy
repositories and modules, which is the common bridge when a company has an Ivy repository and a Gradle build
(Gradle repositories and content filtering).
When to choose Ivy today: you have an Ant build you do not want to migrate, you need configurations richer than Maven’s scopes, or you run a repository with a layout or a metadata format that Maven’s resolver cannot read. When not to: a new project with no Ant legacy will be better served by Maven or Gradle, and an Ant build that only needs to download a few JARs from Maven Central may be simpler with the Maven Resolver Ant Tasks, whose model is the same as Maven’s. The migration directions (Ant and Ivy to Maven or Gradle) are in Migrating Between Tools and in Deprecations & Migration.
Source: Apache Ivy: Features
Common problems
-
The
ivy:tasks are undefined. The Ivy JAR is not on Ant’s classpath. See the failing run above: use-lib, copy the JAR to<home>/.ant/lib, ortaskdefit. -
Two Ivy resolves in parallel in one JVM. Ivy is not thread-safe. Do not call
ivy:*tasks from within<parallel>, and be careful withsubantandantcallinside<parallel>. -
~/.ivy2full of stale modules after an Ivy upgrade. Delete the cache once after moving to a new Ivy line, as the release notes advise. -
The wrong Ivy version is used. A JAR in
ANT_HOME/libalways takes precedence over one added withtaskdef, as a comment in the documentation’s own snippet says;ant -diagnosticsincludes a listing of the JARs inANT_HOME/lib. Keep one Ivy on the classpath. -
Everything resolves, but far more than expected is downloaded. The default configuration mapping of a dependency with no
confis*->*, which for a Maven module includes its test dependencies. This is the most expensive Ivy surprise and is demonstrated, with real output, on the next page.