Ivy repository structure for module with multiple builds (profiles)? - ant

I'm using Ant and Ivy for dependency management in a .NET shop and have been having a lot of success, but I can't figure out a solution for this issue. My question pertains to the repository structure for modules that have several different profiles (for lack of
a better term). For example, the module (it's a 3rd party library - Castle) I'm trying to setup in the repository has been compiled against different versions of the .NET platform. This distribution has the following directory structure:
net35/Castle.Core.dll
net40clientprofile/Castle.Core.dll
sl3/Castle.Core.dll
sl4/Castle.Core.dll
My ivysettings.xml file has the File Resolver setup as this:
<filesystem name="fs.resolver" cache="nn.repo.cache">
<ivy pattern="${repository.dir}/[organisation]/[module]/[shortRevision]/[revision]/ivy.xml" />
<artifact pattern="${repository.dir}/[organisation]/[module]/[shortRevision]/[revision]/[artifact].[ext]" />
</filesystem>
At first, I thought configurations could be used for this, but didn't
make much progress. How can I specify an artifact in the Ivy.xml file with the same name more than once? I don't think you can. Also, if I add subdirectories in the repository will I
have to modify my artifact pattern in ivysettings.xml?
What is the recommended approach with Ivy to setting this module up?
What would the Ivy.xml file for this module look like? How would the
ivysettings.xml file need to be modified for this?
Hopefully I don't have to create separate modules for each different compilation of the same version of the library.
Thanks in advance for any help.

In ivy you can add extra attributes to module artifacts.
Project setup:
|-- build.xml
|-- ivysettings.xml
|-- ivy.xml
`-- repository
`-- myorg
`-- Castle
`-- 1.0
|-- ivy.xml
|-- net35
| `-- Castle.Core.dll
|-- net40clientprofile
| `-- Castle.Core.dll
|-- sl3
| `-- Castle.Core.dll
`-- sl4
`-- Castle.Core.dll
ivy.xml
Use a configuration mapping to choose which artifact to download:
<ivy-module version="2.0">
<info organisation="org.demo" module="demo"/>
<dependencies>
<dependency org="myorg" name="Castle" rev="1.0" conf="default->net35"/>
</dependencies>
</ivy-module>
ivysettings.xml
The artifact pattern includes an extra attribute called "profile"
<ivysettings>
<settings defaultResolver="local"/>
<resolvers>
<filesystem name="local">
<ivy pattern="${ivy.settings.dir}/repository/[organisation]/[module]/[revision]/ivy.xml" />
<artifact pattern="${ivy.settings.dir}/repository/[organisation]/[module]/[revision]/[profile]/[artifact].[ext]" />
</filesystem>
</resolvers>
</ivysettings>
repository/myorg/Castle/1.0/ivy.xml
The extra attribute "profile" is used to differentiate between the artifacts within the module. The configurations are used to enable configuration mapping by client modules.
<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra">
<info organisation="myorg" module="Castle" revision="1.0" status="release"/>
<configurations>
<conf name="net35"/>
<conf name="net40clientprofile"/>
<conf name="sl3"/>
<conf name="sl4"/>
</configurations>
<publications>
<artifact name="Castle.Core" type="dll" e:profile="net35" conf="net35"/>
<artifact name="Castle.Core" type="dll" e:profile="net40clientprofile" conf="net40clientprofile"/>
<artifact name="Castle.Core" type="dll" e:profile="sl3" conf="sl3"/>
<artifact name="Castle.Core" type="dll" e:profile="sl4" conf="sl4"/>
</publications>
</ivy-module>

Related

Apache Ivy: Resolve dependency using a pattern

I want to download artifacts using ivy:resolve, but using a pattern that uses the [conf] attribute. So I have defined the following in
IvySettings.xml
<caches defaultCacheDir="${env.IvyLib}\cache" artifactPattern="[conf]\[artifact].[ext]" checkUpToDate="false" />
Notice the pattern artifactPattern="[conf]\[artifact].[ext]", so I want to resolve the dependencies and place them in a folder as per their configuration. I have defined the following configuration in
Ivy.xml
<configurations>
<conf name="ConfGroup1" description="First group of dependencies"/>
<conf name="ConfGroup2" description="Second group of dependencies"/>
</configurations>
<dependencies>
<dependency org="derby-db" name="derby-db" rev="10.2.2.0" conf="ConfGroup1->default">
<artifact name="derby-db" type="zip" ext="zip" />
</dependency>
<dependency org="derby-db" name="derby-db" rev="10.4.1.3" conf="ConfGroup2->default">
<artifact name="derby-db" type="zip" ext="zip" />
</dependency>
</dependencies>
Now the dependencies get resolved fine, but only 1 folder gets created for configuration: default. No folder is being created for ConfGroup1 & ConfGroup2 configurations. How can I be able to create multiple folders as per my defined configurations during resolve?
P.S., I know this can be achieved using ivy:retrieve, but I do not want to use it, because it will involve copying artifacts from ivy cache to another place after ivy:resolve, and I have multi-gigabyte worth of artifacts. Copying them separately will create additional overhead during the build, which I cannot afford due to the project requirements.
The ivy retrieve task has a symlinks option, that can be used to conserve space.
Example
├── build.xml
├── ivysettings.xml
├── ivy.xml
└── target
├── ivy-reports
│   ├── ivy-report.css
│   ├── myorg-mymod-ConfGroup1.html
│   └── myorg-mymod-ConfGroup2.html
└── lib
├── ConfGroup1
│   └── db-derby-10.12.1.1.zip -> /home/mark/.ivy2/cache/db-derby/db-derby/zips/db-derby-10.12.1.1.zip
└── ConfGroup2
└── db-derby-10.11.1.1.zip -> /home/mark/.ivy2/cache/db-derby/db-derby/zips/db-derby-10.11.1.1.zip
build.xml
<project name="demo" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
<property name="build.dir" location="target"/>
<target name="resolve">
<ivy:resolve/>
<ivy:report todir='${build.dir}/ivy-reports' graph='false' xml='false'/>
<ivy:retrieve pattern='${build.dir}/lib/[conf]/[module]-[revision].[ext]' symlink="true"/>
</target>
</project>
ivy.xml
<ivy-module version="2.0">
<info organisation="myorg" module="mymod"/>
<configurations>
<conf name="ConfGroup1" description="First group of dependencies"/>
<conf name="ConfGroup2" description="Second group of dependencies"/>
</configurations>
<dependencies>
<dependency org="db-derby" name="db-derby" rev="10.12.1.1" conf="ConfGroup1->default">
<artifact name="db-derby" type="zip" ext="zip" />
</dependency>
<dependency org="db-derby" name="db-derby" rev="10.11.1.1" conf="ConfGroup2->default">
<artifact name="db-derby" type="zip" ext="zip" />
</dependency>
</dependencies>
</ivy-module>
ivysettings.xml
<ivysettings>
<settings defaultResolver="central"/>
<resolvers>
<ibiblio name="central" m2compatible="true" />
<url name="db-derby">
<artifact pattern="http://ftp.heanet.ie/mirrors/www.apache.org/dist//db/derby/[module]-[revision]/[module]-[revision]-bin.[ext]"/>
</url>
</resolvers>
<modules>
<module organisation="db-derby" resolver="db-derby" />
</modules>
</ivysettings>

Downloading LWJGL natives with Ivy

I'm trying to set up an Ant + Ivy build for a personal project. Everything was making sense, and working nicely, until I got to LWJGL. Everything from LWJGL is resolved, except the natives.
The Readme.md on their website makes it seem that it is possible to get these through Ivy:
LWJGL 3 can be used with Maven/Gradle/Ivy, with the following
dependencies:
org.lwjgl:lwjgl:${version}
org.lwjgl:lwjgl-platform:${version}:natives-windows
org.lwjgl:lwjgl-platform:${version}:natives-linux
org.lwjgl:lwjgl-platform:${version}:natives-osx
The files I want are definitely on the maven central repository, so there must be a way of getting them through Ivy. I have set up my ivy.xml file like so:
<ivy-module version="1.0" xmlns:extra="http://ant.apache.org/ivy/extra">
<info organisation="foo" module="bar"/>
<publications>
<artifact name="baz" type="jar"/>
</publications>
<dependencies>
<dependency org="org.lwjgl" name="lwjgl" rev="3.0.0a"/>
<dependency org="org.lwjgl" name="lwjgl-platform" rev="3.0.0a" extra:classifier="natives-linux"/>
<dependency org="org.lwjgl" name="lwjgl-platform" rev="3.0.0a" extra:classifier="natives-osx"/>
<dependency org="org.lwjgl" name="lwjgl-platform" rev="3.0.0a" extra:classifier="natives-windows"/>
</dependencies>
</ivy-module>
And my resolve task in ant:
<target name="resolve" description="Retrive dependencies with Ivy">
<ivy:retrieve/>
</target>
For some reason, this downloads all the artifacts from "org.lwjgl:lwjgl:3.0.0a" (jar, javadoc, and sources), but does not download any of the natives from "org.lwjgl:lwjgl-platform:3.0.0a". I spent a long time on Google, and finally managed to find the "extra:classifier" syntax in someone else's ivy.xml file on Github, but to no avail (I got my hopes up too early). There must be something I'm missing, so I hope someone on SO can help.
Extra artifacts in Maven modules must be explicitly retrieved in the ivy dependency declaration.
You'll also need to specify the pattern used in the retrieve task, because "classifier" is a Maven specific tag and optional.
Example
├── build.xml
├── ivy.xml
└── target
└── lib
├── lwjgl-3.0.0a.jar
├── lwjgl-platform-3.0.0a-natives-linux.jar
├── lwjgl-platform-3.0.0a-natives-osx.jar
└── lwjgl-platform-3.0.0a-natives-windows.jar
build.xml
<project name="demo" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
<property name="build.dir" location="target"/>
<target name="resolve">
<ivy:retrieve pattern="${build.dir}/lib/[artifact]-[revision](-[classifier]).[ext]"/>
</target>
</project>
ivy.xml
<ivy-module version="1.0" xmlns:extra="http://ant.apache.org/ivy/extra">
<info organisation="foo" module="bar"/>
<dependencies>
<dependency org="org.lwjgl" name="lwjgl" rev="3.0.0a" conf="default"/>
<dependency org="org.lwjgl" name="lwjgl-platform" rev="3.0.0a">
<artifact name="lwjgl-platform" type="jar" extra:classifier="natives-linux"/>
<artifact name="lwjgl-platform" type="jar" extra:classifier="natives-osx"/>
<artifact name="lwjgl-platform" type="jar" extra:classifier="natives-windows"/>
</dependency>
</dependencies>
</ivy-module>

Finding dependecies between modules of a legacy ANT project for migration to IVY

I am dealing with a project using using ANT to build the source code into a EAR. The project over couple of years has grown to a mammoth size, more than fifty modules, and not surprisingly it takes 2 hours to build the source code.
The obvious decision that I made was to migrate this to a modular build using IVY for dependency management between sub-modules of the EAR, so I build only the modules that have changed and then package a new EAR every time. I am stuck trying to find out a good way of figuring out dependencies between these sub-modules. Note that 3rd party dependencies were easy to crack. I simply move all that is in the lib folder of these sub-modules to IVY. But, the former is where I am stuck.
This is what they do:
Copy source from all modules to a directory
Compile "everything" into a global.jar
Add this global.jar to the classpath
Build every individual module thereafter
Now how do I figure out that for example Module C depends on module A and B and so A and B should go as ivy dependency in the former? One way could be to add one module at a time in eclipse and try building, and then eleminate failures because of missing classes; but there has to be a better way than this, I cannot imagine spending the next one month of life figuring that out :)
First of all you need to create ivy repository. I don't know how to do it. Try to find it on ivy site. After that you need to create build.xml and ivy.xml file.
Example build.xml which builds some product which depends on module1
<project name="ivy.test" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="resolve">
<!-- this line tells ivy to use ${ivy.settings.file} where are ivy repositories; more info http://ant.apache.org/ivy/history/latest-milestone/settings.html -->
<ivy:configure file="${ivy.settings.file}"/>
<!-- resolve ivy dependencies from ivy.xml and put them in ivy cache dir -->
<ivy:resolve file="${build.dir}/ivy.xml" transitive="false" />
<!-- finally copy resolved dependencies to ${ivy.lib.dir} -->
<ivy:retrieve conf="default" pattern="${ivy.lib.dir}/[artifact].[ext]" />
</target>
</project>
Example ivy.xml used to resolve dependencies (will try to find module1 in one of ivy repository defined in ivysettings file)
<ivy-module version="2.0">
<info organisation="your.organisation" module="modulename">
<ivyauthor name="yourname" />
</info>
<configurations>
<conf name="default" description="default conf" />
</configurations>
<dependencies>
<dependency name="module1" org="your.organisation" rev="latest.release" conf="default->default" />
</dependencies>
</ivy-module>
Example ivy.xml used by module1 project (this project depends on module2 and module3; module1 is also published in repository)
<ivy-module version="2.0">
<info organisation="your.organisation" module="module1"> <!-- module name is used in dependency -->
<ivyauthor name="yourname"/>
</info>
<configurations>
<conf name="default" description="default configuration"/>
</configurations>
<publications>
<artifact name="module" ext="dll" type="dll" conf="default"/>
</publications>
<dependencies>
<dependency name="module2" org="your.organisation" rev="latest.release" conf="default->default" />
<dependency name="module3" org="your.organisation" rev="latest.release" conf="default->default" />
</dependencies>
</ivy-module>

Ivy - resolve same dependency twice (with two different versions), to two different files

I have a special situation where I need to package up some jars, and I need BOTH versions of a jar. My ivy definitions looks like this:
<dependency org="blah" name="blahname" rev="1.0.0" conf="baseline->default" />
I would like the same dependency resolved twice, once with version 1.0.0 and another with say version 2.0.0. Is that possible? What's the easiest way to achieve this.
Use ivy configurations to create and manage custom groups of dependencies.
Example
ivy.xml
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="demo"/>
<configurations>
<conf name="group1" description="First group of dependencies"/>
<conf name="group2" description="Second group of dependencies"/>
</configurations>
<dependencies>
<dependency org="commons-lang" name="commons-lang" rev="2.6" conf="group1->default"/>
<dependency org="commons-lang" name="commons-lang" rev="2.0" conf="group2->default"/>
</dependencies>
</ivy-module>
build.xml
<project name="demo" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="resolve">
<ivy:resolve/>
<ivy:retrieve pattern="lib/[conf]/[artifact]-[revision].[ext]"/>
</target>
</project>
Notes:
This example uses the retrieve task to populate the "lib" directory. See also the "cachepath" and "cachefileset" tasks.
Results
Lib directory is populated with the desired jars.
$ tree
.
|-- build.xml
|-- ivy.xml
`-- lib
|-- group1
| `-- commons-lang-2.6.jar
`-- group2
`-- commons-lang-2.0.jar

ivy - create local repository to pull multiple jar files from same location

I have a local repository, in which i can put one jar and retrieve it using ivy. Now for svnant, I want to put 4 jar files in one folder and try to use ivy to retrieve it. my patten in org/module/version/module-version.jar. how do i perform this.
In your ivysettings.xml file define a filesystem resolver with an artifact pattern matching the location of your 4 jars.
<ivysettings>
<settings defaultResolver="local-repo"/>
<resolvers>
<filesystem name="local-repo">
<ivy pattern="${ivy.settings.dir}/repo/[organisation]/[module]/[revision]/ivy.xml"/>
<artifact pattern="${ivy.settings.dir}/repo/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"/>
</filesystem>
</resolvers>
</ivysettings>
Ivy will then be able to find your jars.
Update
In order to group the 4 jars as one module save the following ivy.xml file and store it with the jars
<ivy-module version="2.0">
<info organisation="myorg" module="svnant" revision="1.0"/>
<publications>
<artifact name="svnant"/>
<artifact name="svnclientadapter"/>
<artifact name="svnkit"/>
<artifact name="svnjavahl"/>
</publications>
</ivy-module>
Note: The revision number in the ivy.xml must match the revision number of the module
The dependency in the ivy.xml file is then
<dependency org="myorg" name="svnant" rev="1.0"/>

Resources