Much ado about scripting, Linux & Eclipse: card subject to change

Showing posts with label ant. Show all posts
Showing posts with label ant. Show all posts

2011-10-26

HOWTO: Use Maven, Ant, and XSLT to scrub unwanted p2 metadata from an update site

Some time ago, I wrote about Using p2.inf to add/remove update sites. Tonight I found a simpler way to remove references in p2 metadata to external 3rd party sites.

For example, say you're repackaging some 3rd party features onto your own site, but don't want those features to provide references to the vendor's own update sites because you want to ensure that your product's site will only result in your sanctioned version being installed.

When you generate an update site, p2 pulls the information in the included features and will result in a section of references in the site's metadata that looks like this:

  <references size="6">
    <repository uri="http://download.eclipse.org/egit/updates" url="http://download.eclipse.org/egit/updates" type="0" options="0"/>
    <repository uri="http://subclipse.tigris.org/update_1.6.x" url="http://subclipse.tigris.org/update_1.6.x" type="1" options="0"/>
    <repository uri="http://download.eclipse.org/egit/updates" url="http://download.eclipse.org/egit/updates" type="1" options="0"/>
    <repository uri="http://subclipse.tigris.org/update_1.6.x" url="http://subclipse.tigris.org/update_1.6.x" type="0" options="0"/>
    <repository uri="http://eclipse.svnkit.com/1.3.x/" url="http://eclipse.svnkit.com/1.3.x/" type="0" options="0"/>
    <repository uri="http://eclipse.svnkit.com/1.3.x/" url="http://eclipse.svnkit.com/1.3.x/" type="1" options="0"/>
  </references>
To remove that, you can play with p2.inf directives, or you can simply perform an XSL transformation on the generated content.xml (inside content.jar, if your metadata is compressed) to remove the <references/> node:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
        <xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="*">
        <xsl:copy >
                <xsl:for-each select="@*">
                        <xsl:copy />
                </xsl:for-each>
                <xsl:apply-templates />
        </xsl:copy>
</xsl:template>
<xsl:template match="references" />
</xsl:stylesheet>
If you're generating your update site w/ Tycho, this transform can be called via a simple Ant script:

       <target name="remove.references">
                <!-- requires ant-contrib only if you like using if-then-else structures -->
                <if>
                        <available file="${update.site.source.dir}/content.jar" type="file" />
                        <then>
                                <unzip src="${update.site.source.dir}/content.jar" dest="${update.site.source.dir}" />
                                <delete file="${update.site.source.dir}/content.jar" />
                        </then>
                </if>
                <copy file="${update.site.source.dir}/content.xml" tofile="${update.site.source.dir}/content.old.xml" overwrite="true" />
                <xslt style="remove-references.xsl" in="${update.site.source.dir}/content.old.xml" out="${update.site.source.dir}/content.xml" />
                <zip destfile="${update.site.source.dir}/content.jar" basedir="${update.site.source.dir}" includes="content.xml" />
                <delete file="${update.site.source.dir}/content.xml" />
                <delete file="${update.site.source.dir}/content.old.xml" />
        </target>

Then, in your site's pom.xml, to call the Ant script, do this:

       <build>
                <plugins>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-antrun-plugin</artifactId>
                                <!-- make sure this variable is defined, eg., set to 1.3 -->
                                <version>${maven.antrun.plugin.version}</version>
                                <executions>
                                        <execution>
                                                <id>install</id>
                                                <phase>install</phase>
                                                <configuration>
                                                        <quiet>true</quiet>
                                                        <tasks>
                                                                <!-- called AFTER generating update site + zip to tweak content -->
                                                                <ant antfile="build.xml">
                                                                        <property name="SOME_ANT_VARIABLE" value="${SOME_MAVEN_VARIABLE}" />
                                                                </ant>
                                                        </tasks>
                                                </configuration>
                                                <goals>
                                                        <goal>run</goal>
                                                </goals>
                                        </execution>
                                </executions>
                                <dependencies>
                                        <!-- some dependencies your ant script might need -->
                                        <dependency>
                                                <groupId>commons-net</groupId>
                                                <artifactId>commons-net</artifactId>
                                                <version>1.4.1</version>
                                        </dependency>
                                        <dependency>
                                                <groupId>org.apache.ant</groupId>
                                                <artifactId>ant</artifactId>
                                                <version>1.7.1</version>
                                        </dependency>
                                        <dependency>
                                                <groupId>org.apache.ant</groupId>
                                                <artifactId>ant-nodeps</artifactId>
                                                <version>1.7.1</version>
                                        </dependency>
                                        <dependency>
                                                <groupId>org.apache.ant</groupId>
                                                <artifactId>ant-trax</artifactId>
                                                <version>1.7.1</version>
                                        </dependency>
                                        <dependency>
                                                <groupId>org.apache.ant</groupId>
                                                <artifactId>ant-commons-net</artifactId>
                                                <version>1.7.1</version>
                                        </dependency>
                                        <dependency>
                                                <groupId>org.apache.ant</groupId>
                                                <artifactId>ant-apache-regexp</artifactId>
                                                <version>1.7.1</version>
                                        </dependency>
                                        <dependency>
                                                <groupId>ant-contrib</groupId>
                                                <artifactId>ant-contrib</artifactId>
                                                <version>1.0b3</version>
                                        </dependency>
                                </dependencies>
                        </plugin>
                </plugins>
        </build>

I suppose there's probably a way to call a transform directly from Maven w/o the Ant wrapper, but this allows unpacking and repacking of the content.jar to get at the content.xml file.

2011-02-09

Simplifying The p2 Process, Part 2: Target Platform Repos

In Part 1 of this series, I looked at use of composite repos to provide a way of combining update sites into a single URL for ease of use and a single point of entry from which to do updates.

Defining a Target

Now, I'd like to talk about how to escape the proliferation of zips needed to establish a target platform. For those unfamiliar with the term "target platform", it's either the installed base against which you're compiling your code, or it's the collection of things you have to install first before you can install something on top of that.

For the JBoss Tools case, we have at least 8 prereqs for installation. Here's what you had to install prior to JBoss Tools 3.1.1:

Now, admittedly, because there is also the Ganymede update site, you don't necessarily need to download and unpack all these zips in order to install JBoss Tools - instead, you need only enable the Ganymede site. (Same story for Helios and JBoss Tools 3.2.)

However, to do a reproduceable PDE-based build, you still need to create this base install. Traditionally, PDE's approach was to download and unpack these zips into the root of the Eclipse install running the build. Athena attempted to improve on this situation by allowing you to define a list of update sites and IUs (features and/or plugins) which were needed to define the platform. But it was far from portable, and hardly reusable.

Buckminster (later b3) also approached this problem by creating its own markup for defining what sites and what IUs to install, backed by an EMF model. But rather than dealing with a UI to create the model and populate it, I found it more useful to simply generate an instance of the aggregator model and then use the aggregator to fetch & install IUs. But as the aggregator is simply a wrapper for the underlying p2.mirror and p2.director tasks, you can use those directly too.

But as they say... "Don't bore us, get to the chorus!" So, here's some sample code for the various solutions for build-time provisioning.

  1. Using the buckminster aggregator (properties file) - stopped working for us w/ Eclipse 3.6, so we switched to b3

  2. Using the b3 aggregator (properties file) - stopped worked consistently due to network timeouts resolving deps & fetching IUs.

  3. Using p2.mirror - underlying p2 ant task for mirroring from one or more repos to local disk

  4. Using p2.director - underlying p2 ant task for installing IUs (from local or remote repo) into some target Eclipse

So, with these tools, you could create a p2 repo from other repos - mirroring and installing IUs as needed - and even script an installation. But was there a better way?

Target Platform Definition File

Enter the target platform definition file (.target). This file contains a list of IUs and the p2 repos from which to provision them. So, it's like a b3 aggregator model, or an Athena build.properties file, but abstracted away from the concept of a build, because it can be used for building but ALSO for provisioning a user's installed Eclipse base.

Unfortunately, the Target Platform Definition File editor in Eclipse 3.6 is less than optimal for large targets, or when your internet connection is suboptimal. So, after fighting with it for a while, filing bugs, and ultimately giving up, I went back to my handy-dandy XML editor (often just vim) to maintain it more simply. So rather than having Eclipse automatically install things based on a .target file, I revert to a workflow that actually works: installing by hand from an update site.

While Buckminster does support .target files (or so I've read), I didn't want to be dependent on it any more, preferring a more "pure" solution.

So, based on code from Peter Nehrer (@pnehrer), I then wrote an XSL transform to create a p2.mirror script from a .target file, wrapped with another Ant script (and optionally, a Maven pom.xml script).

And why might you care? Well, this .target file can be used to:

  • Provision a developer's Eclipse, using the Target Platform Definition Editor and a few clicks (when it doesn't time out)
  • Provision a developer's Eclipse via script for offline or multiple users (getting the team up to speed)

And yes, much (or all) of the above can be done w/ Buckminster and/or b3, if you like that approach.

But I prefer to create the .target as input to a build process, rather than being explicitly tied to one. So, as I noted above, if you have a .target file, you can easily generate a p2 repo, and use that repo to run downstream builds. Now, instead of having a half-dozen zips to download and unpack with every build (using the deprecated and unsupported "dropins" method) you can use a fully-p2-friendly repo site which contains everything you need to do your builds - whether you're a Hudson server or a developer working at home or offline.

Benefits

  • Unlike "a collection of zips" this single-source-site can be versioned with each release.

  • It only contains WHAT YOU ACTUALLY NEED rather than extraneous sources and doc and tangential plugins/features you don't. It's a bit like making muffins by first grinding your own flour, but at least you know there's nothing evil in that muffin mix, and you will be able to consistently reproduce the recipe every time, regardless of where you might be on teh interwebz.

  • f you're a keener / beta tester who likes to build against the latest milestone (or even a weekly integration build) of Eclipse 3.next or 4.future, you can use the script above to self-update. So, while the TP itself is a contained snapshot listing the explicit versions of feature groups needed, it can also be run in "get the latest available" mode in order to keep your TP current against some HEAD or trunk development / releases.

  • By splitting the TP out of the build, you can build it upstream. So, where in the past we had one "uberbuild" and an implied TP therein, now we have a TP build job, and it is then shared by the 34 downstream jobs which depend on it for their dependencies.

Shut up and show me the code!

# for the "foo.target" file, build a local target platform repo, fetching the latest versions and updating the .target file
$ ant -f build.xml -DtargetFile=foo.target -DuseLatest=true

# for the "bar.target" file, build a local target platform repo, but fetch only the stated versions of IUs
$ ant -f build.xml -DtargetFile=bar.target -DuseLatest=false

That's it. I also wrap the build.xml ant script w/ a pom which allows it to be called from an upstream Maven/Tycho process, but that's nothing more than just calling the script using the antrun plugin (and a few ant dependencies), like this:

<build>
        <plugins>
                <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-antrun-plugin</artifactId>
                        <version>1.6</version>
                        <executions>
                                <execution>
                                        <phase>validate</phase>
                                        <configuration>
                                                <tasks>
                                                        <ant antfile="build.xml">
                                                                <property name="targetFile" value="multiple.target" />
                                                                <!-- <property name="repoDir" value="/path/to/where/to/provision/repo"/> -->
                                                        </ant>
                                                </tasks>
                                        </configuration>
                                        <goals>
                                                <goal>run</goal>
                                        </goals>
                                </execution>
                     </executions>
                        <dependencies>
                                <dependency>
                                        <groupId>commons-net</groupId>
                                        <artifactId>commons-net</artifactId>
                                        <version>1.4.1</version>
                                </dependency>
                                <dependency>
                                        <groupId>org.apache.ant</groupId>
                                        <artifactId>ant-commons-net</artifactId>
                                        <version>1.7.1</version>
                                </dependency>
                                <dependency>
                                        <groupId>org.apache.ant</groupId>
                                        <artifactId>ant-trax</artifactId>
                                        <version>1.7.1</version>
                                </dependency>
                        </dependencies>
                </plugin>
 </plugins>
</build>

The rest of the code is here.


In part 3, I'll look back at the success we've had using associate sites instead of asking people to manually add 3rd party URLs when installing JBoss Tools. SPOILER ALERT: one URL is easier for people to use than 6.

In part 4, I'll talk a little about how to prevent your product build from getting updates from unofficial sources, and preload your product with the official sites from which to get updates. Because it's important to balance ease of use with prevention of unsupported features. SPOILER ALERT: may contain p2.inf instructions.

2010-10-08

HOWTO: Find the feature that contains a plugin

Tycho is awesome.

However, like all build systems, it has its limitations.

One such limitation is that when you're building against a target platform, and something's missing, you get errors such as these:

[INFO] Cannot complete the request.  Generating details.
{org.osgi.framework.executionenvironment=OSGi/Minimum-1.0,OSGi/Minimum-1.1, osgi.ws=cocoa, osgi.arch=x86, osgi.os=macosx, org.eclipse.update.install.features=true, org.osgi.framework.system.packages=}
[Software being installed: org.jboss.tools.tptp.feature.feature.group 1.2.0.qualifier, Missing requirement: org.eclipse.tptp.platform.instrumentation.ui 4.4.1.v201009092123 requires 'bundle org.eclipse.hyades.probekit [4.2.0,5.0.0)' but it could not be found, Cannot satisfy dependency: org.eclipse.tptp.platform.instrumentation.ui.feature.group 4.3.1.v201009092123-797908s73533D4H6D56 depends on: org.eclipse.tptp.platform.instrumentation.ui [4.4.1.v201009092123], Cannot satisfy dependency: org.jboss.tools.tptp.feature.feature.group 1.2.0.qualifier depends on: org.eclipse.tptp.platform.instrumentation.ui.feature.group 4.3.0]
[ERROR] Internal error: java.lang.RuntimeException: org.eclipse.equinox.p2.core.ProvisionException: No solution found because the problem is unsatisfiable. -> [Help 1]
org.apache.maven.InternalErrorException: Internal error: java.lang.RuntimeException: org.eclipse.equinox.p2.core.ProvisionException: No solution found because the problem is unsatisfiable.

The important part of that error message is as follows:

org.jboss.tools.tptp.feature.feature.group 1.2.0.qualifier
   requirement: org.eclipse.tptp.platform.instrumentation.ui 4.4.1.v201009092123 
      requires 'bundle org.eclipse.hyades.probekit [4.2.0,5.0.0)' 
         but it could not be found

org.eclipse.tptp.platform.instrumentation.ui.feature.group 4.3.1.v201009092123-797908s73533D4H6D56 
   depends on: org.eclipse.tptp.platform.instrumentation.ui [4.4.1.v201009092123]
     dependency: org.jboss.tools.tptp.feature.feature.group 1.2.0.qualifier 
        depends on: org.eclipse.tptp.platform.instrumentation.ui.feature.group 4.3.0]

So, how do you find which feature contains that plugin, so that you can add it to your target platform?

First, you need access to the repository. If you have direct server access to the repository from which the plugin comes (eg., the TPTP Helios update site), you can run this script in the root of that repository.

If you don't have server access (eg., you can't ssh to dev.eclipse.org and look in ~/downloads/tptp/updates/helios), then you can pull down a zip of the site (or use a p2.mirror script to fetch a copy of the site to your local machine)... and then run this script in the root of that repository.

Essentially the script finds matching feature jar files, unpacks them to extract the feature.xml files therein, and then greps those files for lines which suggest an included plugin matching the pattern for which you're searching:

$ findInFeature platform.probekit
./features/org.eclipse.tptp.platform.probekit_4.5.1.v201009092123-7H7BF8PAkF7B77ZARCNEK.jar
   <plugin
         id="org.eclipse.tptp.platform.probekit"

./features/org.eclipse.tptp.platform.trace_4.5.1.v201009092123-7L7O8bBgJ9E99jAfGWEM.jar
   <plugin
         id="org.eclipse.tptp.platform.probekit.launch"
From there, it's a trivial exercise to add another line item into your target platform file. First, paste in the feature jar:
./features/org.eclipse.tptp.platform.probekit_4.5.1.v201009092123-7H7BF8PAkF7B77ZARCNEK.jar

Then use vim to pattern-replace that string:

:%s/.\+\/\(org.\+\)_\(\d\+.\+\)\.jar/\t\t\t/g

And you'll end up with a new .feature.group added to the target:

<unit version="4.5.1.v201009092123-7H7BF8PAkF7B77ZARCNEK" id="org.eclipse.tptp.platform.probekit.feature.group"/>

2010-06-30

Update Site Aggregation: B3 vs. Tycho

Last year, I used to aggregate update sites with the Buckminster Aggregator, but since that won't install into Eclipse 3.6 (Helios), I had to migrate to the B3 Aggregator. This new version of the Aggregator is greatly expanded and worked fine until recently, when it has begun to suffer from a rather nasty p2 problem: instead of the Director just installing the aggregator into an Eclipse instance prior to then running the aggregation, I get "The copies of profile SDKProfile are not in sync," and the whole process dies. http://www.blogger.com/img/blank.gif

So, in order to find a workaround, I went back to Tycho, and discovered you can merge update sites with little more than two simple files:

  • a site.xml, which lists the features to aggregate and how to categorize them, and
  • a pom.xml to list the source sites and drive the aggregation.

Unfortunately the Tycho solution doesn't include the ability to add associate sites to the metadata after generation, but that can simply be done as a downstream step (Tycho can call Ant using the maven-antrun-plugin).

2010-04-04

Cleaner Ant Build Logs: Get Rid of "Trying to override old definition of task"

If you use macros in Ant, you have probably seen clutter in your log such as

Trying to override old definition of task ...

Here's how to purge this garbage from your log and keep your build output cleaner.

  1. move your macros into a target such as <target name="init">
  2. have your main target(s) depend on the target that defines the macros
  3. call your macros

You can make your log even quieter with -q when running ant, eg., ant -f build.xml -q

Here's a complete example that will first self-bootstrap itself by downloading Ant-Contrib, define two ant macros, and produce very quiet output (unless debug=true):

<project default="run">
 <property name="COMMON_TOOLS" value="${java.io.tmpdir}" />
 <property name="debug" value="false"/>

 <target name="get.ant-contrib" unless="ant-contrib.jar.exists">
  <property name="ANTCONTRIB_MIRROR" value="http://downloads.sourceforge.net/ant-contrib/" />
  <get usetimestamp="true"
       dest="${COMMON_TOOLS}/ant-contrib-1.0b2-bin.zip"
       src="${ANTCONTRIB_MIRROR}/ant-contrib-1.0b2-bin.zip"
  />
  <touch file="${COMMON_TOOLS}/ant-contrib-1.0b2-bin.zip" />
  <mkdir dir="${java.io.tmpdir}/ant-contrib-1.0b2-bin.zip_" />
  <unzip src="${COMMON_TOOLS}/ant-contrib-1.0b2-bin.zip"
         dest="${java.io.tmpdir}/ant-contrib-1.0b2-bin.zip_"
         overwrite="true"
  />
  <copy file="${java.io.tmpdir}/ant-contrib-1.0b2-bin.zip_/ant-contrib/lib/ant-contrib.jar"
        tofile="${COMMON_TOOLS}/ant-contrib.jar"
        failonerror="true"
  />
  <delete dir="${java.io.tmpdir}/ant-contrib-1.0b2-bin.zip_" includeemptydirs="true" quiet="true" />
 </target>

 <target name="init">
  <available file="${COMMON_TOOLS}/ant-contrib.jar" type="file" property="ant-contrib.jar.exists" />
  <antcall target="get.ant-contrib" />

  <taskdef resource="net/sf/antcontrib/antlib.xml">
   <classpath>
    <pathelement location="${COMMON_TOOLS}/ant-contrib.jar" />
   </classpath>
  </taskdef>
  
  <macrodef name="debug">
   <text name="echo" />
   <sequential>
    <if>
     <and>
      <isset property="debug" />
      <istrue value="${debug}" />
     </and>
     <then>
      <echo message="@{echo}" />
     </then>
    </if>
   </sequential>
  </macrodef>

  <macrodef name="list.count">
   <attribute name="list" default="" />
   <sequential>
    <var name="count" value="" />
    <for param="listitem" list="@{list}" delimiter=", ">
     <sequential>
      <var name="count" value="${count}0" />
     </sequential>
    </for>
    <length property="list.count.return" string="${count}" />
   </sequential>
  </macrodef>
 </target>

 <target name="run" depends="init">
  <property name="list" value="foo bar baz"/>
  <list.count list="${list}" />
  <debug>For list [${list}], size = </debug>
  <echo>${list.count.return}</echo>
 </target>

</project>

2010-03-24

I'm in love with Tycho 0.8 and Maven 3

Monday:

Signed up for GitHub, downloaded apache-maven-3.0-alpha-7-bin.tar.gz, and built Tycho from source. Took a bit of path wrangling (namely figuring out that maven runs based on current directory), but it built and most of the tests passed. Not bad for my first day ever using Maven.

# First download Maven3 and unpack into /opt/
export MAVEN_OPTS="-Xmx512m"
export TYCHO_TARGET_PLATFORM=/home/nboldt/eclipse/35clean/eclipse
mvn=/opt/maven/bin/mvn
$mvn clean install -e -V -Pbootstrap-1
$mvn clean install -e -V -Pbootstrap-2 -Dtycho.targetPlatform=$TYCHO_TARGET_PLATFORM
$mvn clean test -e -V -Pits -Dtycho.targetPlatform=$TYCHO_TARGET_PLATFORM

The really confusing part was "what now? what did I just build? And how do I use it?" Answer: You can now run maven3 from .../sonatype-tycho/tycho-its/target/apache-maven-3.0-alpha-7/bin/mvn


Tuesday:

Attended the Sonatype-sponsored Tycho Build Workshop, and amazed Pascal by saying good things about Tycho and Maven3. Apparently I'm known to complain about all things p2, despite my numerous blogs and wiki contributions touting its success and usefulness. Also installed m2eclipse to see how effective the pom editor is.

During the workshop, I got the following JBoss Tools projects to build: jmx, archives, as, flow, jbpm3/4, drools, bpel, smooks, common. That's nearly half our projects! Thanks to Jason and Igor for their invaluable assistance.

The reason it was so easy was that Max had already created a scala script to generate all the pom.xml files we need to build JBoss Tools, and a parent-pom.xml on which those tiny pom.xml files depend. (For me as a Maven noob, not having to think at all about creating poms made this transition a no-brainer. Speaking of no-brainers, my slides from Monday's talk about Dash Athena and Zombies are here (PDF).

As an added bonus, Tycho, being more strict than PDE, exposes missing information in MANIFEST.MF files such as dependencies on plugins. PDE-based builds are apparently more forgiving because they generally include more crap than is actually needed in the target platform against which the build runs; Tycho builds against what you tell it you need. So, the mavenification of JBoss Tools will actually cause us to have better described plugins, and therefore make them easier to build anywhere. I'm very impressed so far.

Unlike Dash Athena which needs to be told all the IUs (features/plugins) against which your project needs to build, Tycho determines this information from your manifests, so the information need not be duplicated.

I still need to look at how to build update sites from the output of a Tycho build, and how to hook in SWTBot/JUnit4 tests. I have a suspicion this may be handled using Buckminster tools such as their Aggregator, or my own custom Ant hackery using the SWTBot wiki docs. Time will tell.


Wed

This morning on a whim I decided to see if I could port Max's scala script (aside: I've never seen scala before yesterday) to generate pom.xml files for EMF or GEF. Success! With some minor tweaks, I've managed to build GEF 3.6 into my local maven repo (~/.m2). Obviously there's more to be done here... but damn, this is easy.

2009-04-02

Using EasyAnt with Ivy to fetch latest compile-time and run-time dependencies

Just started playing with Ivy and EasyAnt today.

Here's a quick guide to getting started with multi-module Ant builds (because the EasyAnt Examples documentation is incomplete). This also demonstrates Ivy's ability to pull the latest version of a dependency from a repository. (And I get to finally try out Alex Gorbatchev's SyntaxHighlighter.)

1. Download:

wget http://www.easyant.org/trac/downloads/5 -O /tmp/easyant-0.5-beta1-full.zip

2. Install as root, usable by all:

sudo su; 
unzip /tmp/easyant-0.5-beta1-full.zip -d /opt/easyant-0.5-beta1; \
cd /opt/easyant-0.5-beta1; \
mkdir modules repository cache; \
chmod -R g+rw *; chgrp -R users *; \
exit

3. Compile multi-module example's core jar:

export EASYANT_HOME=/opt/easyant-0.5-beta1; \
cd /opt/easyant-0.5-beta1/example/example-multimodule/example-core; \
$EASYANT_HOME/bin/easyant -p; \
$EASYANT_HOME/bin/easyant

4. Verify compiled jar:

unzip -l /opt/easyant-0.5-beta1/example/example-multimodule/example-core/target/artifacts/example-core.jar

5. Publish jar:

$EASYANT_HOME/bin/easyant repo-management:install-artifact -Dorg=org.apache.easyant \
  -Dmodule=example-core -Drev=0.1 -Dartifact=target/artifacts/example-core.jar \
  -Dinstall.override=true -Dto.resolver=local

6. Verify published:

unzip -l /opt/easyant-0.5-beta1/repository/org.apache.easyant/example-core/0.1/example-core.jar; \
cat /opt/easyant-0.5-beta1/repository/org.apache.easyant/example-core/0.1/example-core.ivy
<ivy-module version="1.0">
    <info organisation="org.apache.easyant" module="example-core" revision="0.1"/>
</ivy-module>

7. Compile multi-module example's Hello World jar:

cd /opt/easyant-0.5-beta1/example/example-multimodule/example-hello-world; $EASYANT_HOME/bin/easyant

8. Verify compiled jar:

unzip -l /opt/easyant-0.5-beta1/example/example-multimodule/example-hello-world/target/artifacts/example-hello-world.jar

8. Run Hello World app:

cd /opt/easyant-0.5-beta1/example/example-multimodule/example-hello-world; $EASYANT_HOME/bin/easyant run:run
...
run:run:
     [java] Hello World !

BUILD SUCCESSFUL
Total time: 2 seconds

9. Now, recompile the core jar, republish it as 0.2, then recompile the Hello World jar. Verify that the Hello World compilation used the newer 0.2 version instead.

cd /opt/easyant-0.5-beta1/example/example-multimodule/example-core; $EASYANT_HOME/bin/easyant; \
$EASYANT_HOME/bin/easyant repo-management:install-artifact -Dorg=org.apache.easyant \
  -Dmodule=example-core -Drev=0.2 -Dartifact=target/artifacts/example-core.jar \
  -Dinstall.override=true -Dto.resolver=local; unzip -l \
/opt/easyant-0.5-beta1/repository/org.apache.easyant/example-core/0.2/example-core.jar; \
cat /opt/easyant-0.5-beta1/repository/org.apache.easyant/example-core/0.2/example-core.ivy; \
cd /opt/easyant-0.5-beta1/example/example-multimodule/example-hello-world; \
$EASYANT_HOME/bin/easyant; $EASYANT_HOME/bin/easyant run:run
lib-resolve:
:: loading settings :: file = /opt/easyant-0.5-beta1/ivysettings.xml
[ivy:resolve] :: resolving dependencies :: org.apache.easyant#example-hello-world;working@x2lappy
[ivy:resolve]  confs: [default, test]
[ivy:resolve]  found org.apache.easyant#example-core;0.2 in local
[ivy:resolve]  [0.2] org.apache.easyant#example-core;latest.revision
[ivy:resolve] :: resolution report :: resolve 30ms :: artifacts dl 1ms

2009-04-01

Dash Athena: Epic Fail

Damn airport scanners.

On Sunday while I was flying home from EclipseCon, I decided to try out Git, and migrated the whole Dash CVS tree into a local Git repo. Then, I deleted the CVS stuff in dev.eclipse.org because Git is so much better and DVCS is the Way of the Future.

Unfortunately, somewhere between Calgary and Toronto, my hard drive died, taking with it the whole repo.

Since we now have to start over completely from scratch, Andrew and I have decided to take this opportunity to re-architect a few things:

  1. Instead of Ant scripts which wrap & simplify PDE, we're going to use perl scripts which wrap ant4eclipse. No one really cares about OSGi anymore anyway.

  2. Instead of being able to run a build in Eclipse, we're going to support running on MIDP devices only (smartphones) and older hardware (bug 260000). This will make builds much smaller and more portable for everyone.

  3. We're dropping the built-in support for running JUnit tests as part of an automated build, because the Agile way is to do Build Breakage Driven Development (BBDD) rather than TDD.

  4. Because the Hudson instance on build.eclipse.org is only accessible to an elite few (bug 270633), we're dropping that too, in favour of Cruise Control, much lauded by the WTP and Orbit dev teams for its friendly user interface and many extensible configuration options.

Should you have any concerns with this new plan, don't hesitate to post your comments here. We value the community's input, and will take your thoughts under advisement. Then ignore them and do what we want.

2008-12-08

Obfuscation 101: Ant-contrib

I have recently fallen in love with ant-contrib. I'd still rather write Bash scripts, but if one must interact w/ Ant, ant-contrib is the only way to survive it. Without it, you don't have variables, for-loops, or if-elseif-then trees.

Of course, with every love there are moments of extreme angst. For example, I've been fighting with this error for the last 12 hrs, on and off, as I've been trying to resolve bug 256440:

Invalid type class org.apache.tools.ant.TaskAdapter used in For task, it does not have a public iterator method

What does that mean? It means I'm a dumbass.

Though I should know better, I rely on tools such as Eclipse's Ant editor to tell me when I've messed up task syntax. And though it can do CTRL-SPACE completion for the <for> task, the editor doesn't mark this invalid (if I've already typed it in).

<for ...>
 <if>
   ...
 </if>
</for>

The fix?

<for ...>
 <sequential>
   <if>
     ...
   </if>
 </sequential>
</for>

Ultimately, though, I wish error messages would be written with the end-user in mind. The above problem would have been solved in seconds had it been simply "For task cannot contain nested If task... dumbass." :)

2008-12-02

My love-hate with SVN

Since joining JBoss, a division of Red Hat, I've gotten to know the foibles of SVN rather intimately. Here are my two favourites, both encountered this week:

  1. This client is too old to work with working copy; please get a newer Subversion client.
    Problems reported while synchronizing SVNStatusSubscriber. 2 of 3
    resources were synchronized.
    An error occurred synchronizing /devstudio-workspace: Error
    getting status for resource P/devstudio-workspace
    org.tigris.subversion.javahl.ClientException: svn: This client is
    too old to work with working copy; please
    get a newer Subversion client

    This happens if you use SVN 1.5.4 and Subclipse 1.4.6 with SVNKit & JavaHL plugins. Solution? Switch to Subversive 0.7.5, or follow this advice (so I'm told, I haven't tried yet).

  2. Installing subversion-javahl-1.5.4-3.i386 (on Fedora 10 Rawhide) causes Ant 1.7.1 to fail to do SVN checkouts.
    (from /var/log/yum.log)
    Nov 27 19:51:47 Installed: subversion-javahl-1.5.4-3.i386
    [java] fetchElement:
    [java] #
    [java] # An unexpected error has been detected by Java Runtime Environment:
    [java] #
    [java] #  SIGSEGV (0xb) at pc=0x05984ec5, pid=24986, tid=3086982032
    [java] #
    [java] # Java VM: Java HotSpot(TM) Server VM (11.0-b15 mixed mode linux-x86)
    [java] # Problematic frame:
    [java] # C  [libapr-1.so.0+0x1fec5]  apr_threadkey_private_get+0x15
    [java] #
    [java] # An error report file with more information is saved as:
    [java] # /opt/public/jbt-jbds/nightly-20081128-0002/org.jboss.ide.eclipse.
             releng/builders/hs_err_pid24986.log
    [java] #
    [java] # If you would like to submit a bug report, please visit:
    [java] #   http://java.sun.com/webapps/bugreport/crash.jsp
    [java] # The crash happened outside the Java Virtual Machine in native code.
    [java] # See problematic frame for where to report the bug.
    [java] #
    [java] Java Result: 134
    (from /var/log/yum.log)
    Dec 02 11:19:23 Erased: subversion-javahl

    And now it works again!