Published artifact patterns in Ivy - ant

When I resolve artifacts from my repository (e.g. filesystem), I use two artifact patterns:
<artifact pattern="${location}/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"/>
<artifact pattern="${location}/[organisation]/[module]/[revision]/[artifact]-[revision]-[type]s.[ext]"/>
The first one is for jar files, and the second one is for sources or other types of artifacts.
I'd like to be able to publish artifacts the same way, but I don't know how.
Using just the patterns above, the publish task seems to consider only the first one, thus removing the type. If multiple artifacts have the same name and extension, they will be overwritten.
If I just use the second pattern, then for jar artifacts it makes ${artifact}-${revision}-jars.jar which is really ugly.
Finally, it seems to be possible to have optional parts in patterns, such as:
<artifact pattern="${location}/[organisation]/[module]/[revision]/[artifact]-[revision](-[type]s).[ext]"/>
But the -[type]s part is omitted only if the type is null or empty, and I'd like the type to remain "jar", in which case the part is not omitted.
So is there any other way?

Why don't you use ivy.xml files for artifacts? You should need to create ivy.xml and place them to your module folder, near jar files. ivy.xml example:
<ivy-module version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
<info organisation="com.organisation" module="foo" revision="1.0"/>
<publications>
<artifact name="foo"/>
<artifact name="foo-sources" type="source" ext="zip"/>
</publications>
</ivy-module>
Then you should define ivy pattern in your resolver:
<ivy pattern="${location}/[organisation]/[module]/[revision]/ivy.xml"/>
Now if you use <dependency org="com.organisation" name="foo" rev="1.0"/> you will get all artifacts described in ivy.xml. There is a way to select only the needed artifacts.

Not really a solution, but a slightly better way is:
<artifact pattern="${location}/[organisation]/[module]/[revision]/[type]s/[artifact]-[revision].[ext]"/>

I struggled with the same.
I found the solution, you can use:
[artifact](-[classifier]).[ext]
-classifier will be null/empty on the jar on sources/javadoc-jars it contains -sources/-javadoc.jar
I know its been a while, but I found this question by google. So for any future person it will be helpful I think.

Related

Multiple configuration files for the ProGuard Ant task

I am using the ProGuard ant task, and everything is great, except that my ProGuard configuration file is huge. Also, different tasks use different ProGuard configuration files, and there is a lot of copy-pasting that I would like to refactor into separate .pro files.
<taskdef resource="proguard/ant/task.properties" classpath="C:/Program Files/proguard4.7/lib/proguard.jar"/>
<target name="obfuscated_jar" depends="raw_jar">
<proguard configuration="core.pro lib1.pro lib2.pro">
<outjar path="prog_obfuscated.jar"/>
</proguard>
</target>
The above doesn't work, because it treats the multiple .pro files as one big filename. I'm a known idiot w.r.t. ant, am I missing something obvious? Thanks!
You can create a single main .pro file that contains -include options pointing to your actual .pro files.
This answer isn't great, but it works...
<taskdef resource="proguard/ant/task.properties" classpath="C:/Program Files/proguard4.7/lib/proguard.jar"/>
<target name="obfuscated_jar" depends="raw_jar">
<concat destfile="proguard_temp.pro">
<filelist dir="." files="core.pro,lib1.pro,lib2.pro"/>
</concat>
<proguard configuration="proguard_temp.pro">
<outjar path="prog_obfuscated.jar"/>
</proguard>
<delete file="proguard_temp.pro"/>
</target>
Looks like only one file allowed in configuration attribute.
Edited
And attributes allowed only on <proguard> element. I have another possible solution. Try to concatenate your config-files into one with Ant concat-task and pass this temporary file to <proguard configuration=""> attribute.
Also, it's possible to modify ProGuardTask-class to accept several files as arguments and concatenate them later. And same result could be achieved with Ant macrodef .

Findbugs ant task submitting several dynamically detected JAR files for analysis

I'm currently looking to run static analysis over a pre-existing project. As the project is created and supplied by an off-site company, I cannot change the build process radically.
The project is split into a lot of sub-modules, located in various places. For other analyisi tools (JDepend, Google Testability Explorer, etc.), I have dynamically detected all build JAR files into a path element as follows:
<path id="built-libs">
<fileset dir="${overall-base}">
<include name="${some-common-base}/**/lib/*.jar" />
</fileset>
</path>
<property name="built-libs-string" refid="built-libs" />
For some tools, I use the build-libs, for others I use the string (in classpath form; x.jar;y.jar).
The trouble is, FindBugs uses a completely different format to any other;
<class location="x.jar"/>
<class location="y.jar"/>
...
Now, I could list all the JAR files manually, but then run the risk of this list going out of synch with the other tool's lists, or of introducing typos.
Another complication is that I also want to run the reports in Jenkins, in this case the extract directory for individual modules will depend on the job that has previously built the module (pipeline builds, modules extracted from SCM and built in parallel, the reporting occurring at the end of the pipline).
I could make a call out to the OS to run FindBugs, passing in the JARs in a space separated list (as in Invoking FindBugs from Ant: passing a space-separated list of files to java). However, I prefer a, Ant solution to an OS <exec... hack.
Note I know I have a similar problem for the sourcepath element, however, I'm assuming that solving the class element problem also solves the sourcepath one.
Ideally, FindBugs should be taking a resource collection rather than separate class elements. I'm not familiar with FindBugs, so I can't comment on why they have chose to go the class element route instead of a resource collection, however your comment about using exec implies that using a resource collection is a valid design alternative.
I would try rolling your own Ant macro, which invokes FindBugs directly using the java task. This should give you the control you need and avoiding the redundancy that the FindBugs Ant task would introduce.
Another option (which is an ugly hack) is to use the fileset to write a mini ant file with a FindBugs target, which you then invoke using the ant task. shudders
The Findbugs Ant task allows you to specify a filelist which can be used to specify multiple files. Quoting from the Findbugs documentation
"In addition to or instead of specifying a class element, the FindBugs
task can contain one or more fileset element(s) that specify files to
be analyzed. For example, you might use a fileset to specify that all
of the jar files in a directory should be analyzed."
Example that includes all jars at ${lib.dir}:
<findbugs home="${findbugs.home}" output="xml" outputFile="findbugs.xml" >
<auxClasspath path="${basedir}/lib/Regex.jar" />
<sourcePath path="${basedir}/src/java" />
<fileset dir="${lib.dir}">
<include name="*.jar"/>
</fileset>
</findbugs>

Enumerating Folders With MSBuild

I am coming up on the end stages of an Asp.Net MVC 1.0 project in VS2008 / Framework 3.5, and trying to do some performance optimizations. In my project, I have a few different "themes" that are used, depending on the role of the logged in user. My themes folder structure is like so...
\Themes
\Theme1
\Css
\Folder1
\CssFile1.css
\CssFile2.css
\Folder2
\CssFile1.css
\CssFile2.css
\Images
<Images go here>
\Theme2
\Css
\Folder1
\CssFile1.css
\CssFile2.css
\Folder2
\CssFile1.css
\CssFile2.css
\Images
<Images go here>
As new customers come on board, new themes will be added to this folder structure.
I am using the Yahoo! UI Library: YUI Compressor for .Net
(which is really cool) to minify and merge my css (and js) files.
I followed the example at http://yuicompressor.codeplex.com/wikipage?title=Sample%20MSBuild.xml%20File&ProjectName=yuicompressor to run an MSBuild script via a post-build event to do the minify/merge tasks.
Everything works great, except that when I use something like <CssFiles Include="..\Themes\**\*.css" /> in my ItemGroup to specify where to get the css files, all css files from every theme are merged into one file, like this...
\Themes
\SylesSheetFinal.css
What I want instead is to merge only the css under the themes, creating one css file for each...
\Themes
\Theme1
\StyleSheetFinal1.css
\Theme2
\StyleSheetFinal2.css
I am really new to MSBuild. Does anyone know how I can modify the sample to automatically walk over each of the theme folders and create a minified/merged stylesheet for each? The themes can be added or removed quite often, so I don't want to have to manually include each theme path to my ItemGroup. Instead, I want the MSBuild script to walk the subfolders underneath the Themes root automatically, regardless of the number of folders.
Thanks!
What you are trying to do can be accomplished with batching. Batching is the process of executing a specific task (or target) once for each unique batch. There are two types of batching; Task Batching and Target Batching. Task batching is the most common and what I think you need, based on the info provided here. Batching can be kind of confusing, but it is not too bad once you get a grasp on it.
Batching always involves the %() operator. Here is an example of Task Batching.
<Project ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Batching01.proj -->
<ItemGroup>
<Files Include="src\Src01.cs"/>
<Files Include="src\Src02.cs"/>
<Files Include="src\Src03.cs"/>
<Files Include="src\Src04.cs"/>
</ItemGroup>
<Target Name="Demo">
<!-- Not batched, i.e. Files is flattened and sent to the Message task -->
<Message Text="Files: #(Files)"/>
<Message Text="================" Importance="high" />
<Message Text="Filename: %(Files.Filename)" Importance="high" />
</Target>
</Project>
The output would be:
Files: src\Src01.cs;src\Src02.cs;src\Src03.cs;src\Src04.cs
================
Filename: Src01
Filename: Src02
Filename: Src03
Filename: Src04
It is too tough to fully describe batching in this post, but I've put together some really great resources available online at http://sedotech.com/Resources#Batching.

Avoiding re-building prerequisites in Ant

I have an existing Ant project and would like to speed up the build process
by avoiding re-building components that are already up to date.
Ant permits you to specify that one target depends on another, but by
default every prerequisite is always rebuilt, even if it is already up to
date. (This is a key difference between Ant and make. By default, make
only re-builds a target when needed -- that is, if some prerequisite is
newer.)
<uptodate property="mytarget.uptodate"> // in set.mytarget.uptodate task
...
</uptodate>
<!-- The prerequisites are executed before the "unless" is checked. -->
<target name="mytarget" depends="set.mytarget.uptodate" unless="mytarget.uptodate">
...
</target>
To make Ant re-build prerequisites only if necessary, there seem to be two
general approaches within Ant.
The first approach is to use the uptodate task to set a property. Then,
your task can test the property and build only if the property is (not)
set.
<uptodate property="mytarget.uptodate"> // in set.mytarget.uptodate task
...
</uptodate>
<!-- The prerequisites are executed before the "unless" is checked. -->
<target name="mytarget" depends="set.mytarget.uptodate" unless="mytarget.uptodate">
...
</target>
An alternate first approach is to use the outofdate task from ant contrib.
It's nicer in that it is just one target without a separate property being
defined; by contrast, outofdate requires separate targets to set and to
test the property.
The second approach is to create a <fileset> using the <modified>
selector. It calculates MD5 hashes for files and selects files whose MD5
differs from earlier stored values. It's optional to set
<param name="cache.cachefile" value="cache.properties"/>
inside the selector; it defaults to "cache.properties". Here is
an example that copies all files from src to dest whose content has
changed:
<copy todir="dest">
<fileset dir="src">
<modified/>
</fileset>
</copy>
Neither of these is very satisfactory, since it requires me to write Ant
code for a process (avoiding re-building) that ought to be automatic.
There is also Ivy, but I can't tell from its documentation whether it
provides this feature. The key use case in the Ivy documentation seems to
be downloading subprojects from the Internet rather than avoiding wasted
work by staging the parts of a single project. Maven provides similar
functionality, with the same use case highlighted in its documentation.
(Moving an existing non-trivila project to Maven is said to be a nightmare;
by contrast, starting greenfield development with Maven is more palatable.)
Is there a better way?
This conditional compilation of a large build is a feature of make that I initally missed in ANT. Rather than use target dependencies, I'd suggest dividing your large project into smaller modules, each publishing to a common shared repository.
Ivy can then be used to control the component versions used by the main module of the project.
<ivy-module version="2.0">
<info organisation="com.myspotontheweb" module="multi_module_project"/>
<publications>
<artifact name="main" type="jar"/>
</publications>
<dependencies>
<dependency org="com.myspotontheweb" name="component1" rev="latest.integration"/>
<dependency org="com.myspotontheweb" name="component2" rev="latest.integration"/>
<dependency org="com.myspotontheweb" name="component3" rev="latest.integration"/>
<dependency org="com.myspotontheweb" name="component4" rev="latest.integration"/>
</dependencies>
</ivy-module>
The ivy:retrieve task will only download/copy one of the sub-modules if they have changed (published from their build files)
It all sounds more complicated but maybe you're already sub-dividing the project within your build file.... For example, if your ANT uptodate task is being made dependent on one the build artifacts.

Filter a fileset referenced using a refid

I have a fileset (which is returned from the Maven Ant task), and it contains all the jars I need to repack. This fileset is referenced by a refid. I only want to include our own jars, so I would like to filter that. But Ant filesets don't support any further attributes or nested tags if a refid is used.
For example, if the fileset is:
org.foo.1.jar
org.foo.2.jar
log4j.jar
and I want to have a fileset which contains only
org.foo*.jar
How would I do that?
Try using a restrict resource collection, which you can use like a fileset in any task that uses resource collections to select the groups of files to operate on.
For example, for a fileset returned from your Maven task referenced via an id called dependency.fileset you can declare a restrict resource collection like so:
<restrict id="filtered.dependencies">
<fileset refid="dependency.fileset"/>
<rsel:name name="org.foo*.jar"/>
</restrict>
Note you'll have to declare the resource selector namespace as it isn't part of the built-in Ant namespace:
<project xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors">
...
</project>
From here you can reference your restrict resource collection in a similar fashion to how you would reference your fileset. For example, to create backups of your filtered set of files:
<copy todir=".">
<restrict refid="filtered.dependencies"/>
<globmapper from="*" to="*.bak"/>
</copy>
Of course you can inline your restrict resource collection if you so desire:
<copy todir=".">
<restrict>
<fileset refid="dependency.fileset"/>
<rsel:name name="org.foo*.jar"/>
</restrict>
<globmapper from="*" to="*.bak"/>
</copy>
Have a look at the Ant documentation on resource collections for further information.
I think you'll need to write an ant task for that. They're pretty easy to write though.
See http://ant.apache.org/manual/develop.html#writingowntask
In your task, you'll need to call getProject() and ask it to give you the fileset, walk through it, and create a new one.
I 'm using Ant with Ivy. With the help of Ivy it is possible to filter dependencies for retrieval, with the following code in ivy.xml:
<dependency name="Project1" rev="latest.integration" transitive="true" conf="modlibs">
<exclude name="${exclusionRegEx}" matcher="regexp" />
</dependency>
<dependency name="Project2" rev="latest.integration" transitive="false" conf="modules"/>
Maybe a quick look at the Ivy source 'll help?
If you are using a sufficiently recent version of Ant and the JDK, for example, Ant 1.7 and JDK 6, then you can use the optional script task to do what you want. (Earlier versions may also work.) The page I linked to, if you scroll down to the text "The goal is to list the filesizes" then you'll see a sample script that creates a Fileset.
This isn't for the faint of heart, and a custom ant task you write yourself will probably be more flexible. But I wanted to point out the option.

Resources