This post is intended for everyone who develops Java applications for Eclipse Rich Client Platform (RCP). You will find here a working Tycho configuration on the working demo project. That project can be built fully automatically with Tycho on your CI server e.g. Jenkins.

If you have developed Eclipse RCP before, you may also come to the conclusion that PDE-Build out of Eclipse IDE is not really an appropriate and stable way to build serious, production-ready applications. But also automation of PDE Build was not a straightforward task, and a such is still not well documented.

Further maybe you heard about some alternatives like buckminister approach or athena. However tycho seem to be the best of them.

Tycho for PDE Build

Technically tycho PDE build is a set of maven plugins. Let it be said at the beginning, tycho tries to use all the eclipse PDE/JDT metadata first. One of the goals of tycho project is to minimize configuration duplication between maven artifacts and Eclipse PDE project.

Here is the self-speaking list of tychos packaging types, i will covers some of them more detailed.

  • eclipse-plugin result in Eclipse Plug-In bundle
  • eclipse-test-plugin result in a test Plugin
  • eclipse-feature which eclipse feature as Result
  • eclipse-application builds Eclipse Application
  • eclipse-repository builds repository an executables
  • eclipse-update-site responsible for update-sites

Tycho current release is 0.13.0 and is used in my example.

Example Application

In this article used application is Open Source and can be cloned from GitHub RCP Life Game. This app is a very basic but working implementation of Conway’s Life Game. Technically it consists of:

  • one parent project,
  • one plugin project,
  • one feature,
  • as well as one target
  • and one repository project

Clone the Repository and you will be able to start the game out of eclipse IDE by clicking on the “Launch Eclipse Application” Button in the open org.holbreich.lfgm.eclipse-repository/example.product file. As you know every RCP application should be built with a fixed set of the eclipse platform plugins so-called target platform. That is where we start.

Target platform

Configuration of the target platform in eclipse can be stored in a file with file-extension .target . So my example target platform definition looks like the following.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde version="3.6"?>
<target name="eclipse 3.7.1 (indigo)" sequenceNumber="16">
 <locations>
  <location includeAllPlatforms="false" includeMode="planner" includeSource="false" type="InstallableUnit">
  <unit id="org.eclipse.rcp.source.feature.group" version="3.7.1.r37x_v20110729-9DB5FmNFnFLSFCtLxnRfMqt15A4A"/>
  <unit id="org.eclipse.equinox.sdk.feature.group" version="3.7.1.R37x_v20110907-7M7W8h8eNV4Vrz-hz01A7SL_MhZP"/>
  <unit id="org.eclipse.pde.feature.group" version="3.7.1.r37x_v20110810-0800-7b7qFVtFEx2XnmZ4jlM5mjM"/>
  <repository location="http://download.eclipse.org/releases/indigo"/>
 </location>
</locations>
</target>

Maven’s central project configuration file is pom.xml. The Element build of the pom.xml is a central element where all the needed (plugin) declarations are placed, so that maven is able to get the knowledge about how to compile and build desired artifacts. Typically you’ll find here the definition of needed maven plugins with their configurations, executions, and goals[^1].

The target platform which was mentioned above is introduced to maven through mavens’s build-helper-maven-plugin as an artifact. See the configuration section of that plugin.

<build>
    <plugins>
       <plugin>
        <!-- Id and version of build helper plugin -->
    <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.3</version>
        <executions>
        <execution>
          <id>attach-artifacts</id>
          <phase>package</phase>
          <goals>
            <goal>attach-artifact</goal>
          </goals>
          <configuration>
                <artifacts>
                             <artifact>
                 <file>indigo.target</file>
                 <type>target</type>
                 <classifier>indigo</classifier>
                 </artifact>
                 </artifacts>
          </configuration>
        </execution>
        </executions>
    </plugin>
    </plugins>
</build>

Now our target platform can be used whenever we like and we would like to use it nearly everywhere, so that leads to the idea to provide this last configuration only once in the parent pom.xml of the maven parent project for the whole Life Game Application.

Parent project

A parent project is a maven way to handle a kind of configuration inheritance. My so-called parent project defines some useful and multiply used things for all of the modules used in the current application and also provides me the ability to build the whole application at once. Let me show you the whole file here, excuse me if it appears a bit unreadable now.

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.holbreich.lfgm</groupId>
  <artifactId>parent</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>Shuron's Life Game Maven Parent Project</name>

  <properties>
    <!-- just some properties, tycho version and encoding -->
  <tycho-version>0.13.0</tycho-version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
<!-- eclipse IDE flat project style. So parent project is only sibling folder
   therefore has to acces his modules by "../". Here are all the child modules. -->
    <modules>
        <module>../org.holbreich.lfgm</module>
        <module>../org.holbreich.lfgm.target</module>
        <module>../org.holbreich.lfgm.feature</module>
        <module>../org.holbreich.lfgm.eclipse-repository</module>
    </modules>

    <build>
        <plugins>
                  <!-- defintion of tychos target-platform-configuration plugin -->
            <plugin>
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>target-platform-configuration</artifactId>
                <version>${tycho-version}</version>
                <configuration>
                    <resolver>p2</resolver>
                    <target>
                            <!--  A reference to target platform artefact: -->
                        <artifact>
                            <groupId>org.holbreich.lfgm</groupId>
                            <artifactId>target-platform</artifactId>
                            <version>1.0.0-SNAPSHOT</version>
                            <classifier>indigo</classifier>
                        </artifact>
                    </target>
                    <ignoreTychoRepositories>true</ignoreTychoRepositories>
                           <!-- Environment configuration for the taget platform -->
                    <environments>
                        <environment>
                            <os>win32</os>
                            <ws>win32</ws>
                            <arch>x86</arch>
                        </environment>
                        <environment>
                            <os>linux</os>
                            <ws>gtk</ws>
                            <arch>x86</arch>
                          </environment>
                    </environments>
                </configuration>
            </plugin>
                 <!-- defintion of tycho-maven-plugin -->
            <plugin>
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>tycho-maven-plugin</artifactId>
                <version>${tycho-version}</version>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
</project>

As already mentioned in the comments of the pom.xml that defines known modules and a set of plugins with their configuration. Actually two plugins:

  • target-platform-configuration - which refers to already discussed target platform artifact and provides additional environment configuration.
  • Tycho-maven-plugin - which defines additional packaging types like eclipse-plugin and eclipse feature.

That configuration allows you to minimize pom.xml of the plugins and features.

Plug-in pom.xml

As all used plugins are already defined in the parent, the actual the pom.xml file of the plugin project is pretty short and looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
        http://maven.apache.org/xsd/maven-4.0.0.xsd"
    xmlns="http://maven.apache.org/POM/4.0.0" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>org.holbreich.lfgm</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>eclipse-plugin</packaging>
    <!-- Parent reference -->
    <parent>
         <artifactId>parent</artifactId>
         <groupId>org.holbreich.lfgm</groupId>
         <version>1.0.0-SNAPSHOT</version>
         <relativePath>../org.holbreich.lfgm.parent/pom.xml</relativePath>
      </parent>
</project>

And this is great because in a large application you will have many of the plugins with their simple pom files. You see the important moment here is the reference to the parent and declaration of the packaging type eclipse-plugin. Eclipse Feature project uses eclipse-feature packaging target, but looks most the same, so i’m not showing it here.

Repository

And finally, Repository Plugin comes into play. It’s defines routines for the last assembly and packing of a product. Here I bring only the build element of the pom.xml file where the execution element of tycho-p2-director-plugin defines these two goals.

<build>
    <plugins>
    <plugin>
        <groupId>org.eclipse.tycho</groupId>
        <artifactId>tycho-p2-director-plugin</artifactId>
        <version>${tycho-version}</version>
        <executions>
            <execution>
                <id>materialize-products</id>
                <goals>
                    <goal>materialize-products</goal>
                </goals>
            </execution>
            <execution>
                <id>archive-products</id>
                <goals>
                    <goal>archive-products</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    </plugins>
</build>

Now here we are. I’ve didn’t mentioned further eclipse artifacts like feature.xml or some.project, they stay as usual and must work also without maven.

To get started you can start to build your application by executing maven goals e.g. mvn clean install or run this in a configuration in your CI server.

Build automation with Jenkins CI

The showed configuration is ready for automation as it is. You can automate this very simply with a standard Jenkins maven job. Provide git checkout path, for all the projects and define e.g. clean installas maven goals for execution on parent project’s pom.xml in your Jenkins Job.

However zipped standalone executables for Linux and Windows can be found under org.holbreich.lfgm.eclipse-repository/target/products/ in the project workspace after successful build. Have fun and let me know if you missed something i this description.

Let me know if something of the above topic is something of your interest.

As well you are invited to comment on your solutions and best practices.

Further Readings

Thank you for reading if you got here ;)


  • Update Okt 2013: I have consolidated build process. It is still Tycho v 0.13.0. Build works on Travis CI now.