Skip to content
Alexander Holbreich
Go back

Building Eclipse Rich Client Application automatically (Tycho)

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.

Archived comments (18)

These comments were migrated from Disqus and are no longer accepting replies.

  • jaklumow

    Thanks for posting.
    Is it possible to see the whole approach?
    I mean how it works toghether with a maven repository? how to release the artefacts? sorry i'm not familar with maven.

  • AlexH

    Thank you for this question. This is a question for addtional Post. Unfortunately my maven repository is not ready yet:( But in general tycho don't need more magic than normal release of maven artefacts. I'll try to post about it it in the next time.

    P.S. Maven Release Plugin is good place to start reading about "releasing of artefacts".

  • tostao

    Hello Alexander, is's fantastic post,now i know much more howbuild RCP by maven.
    I checkouted Your game of life,when i execute
    mvn eclipse:elipse (to generate .project,.classpath)
    everything is ok, when i execute mvn eclipse:clean to delete files as above everything works fine,
    but when i try to generate this file one more time (mvn eclipse:eclipse) maven shows error:
    [INFO] Shuron's Life Game Maven Parent Project SUCCESS [1.419s]
    [INFO] org.holbreich.lfgm .............. FAILURE [0.374s]
    [INFO] target-platform ......................... SKIPPED
    [INFO] org.holbreich.lfgm.feature ............. SKIPPED
    [INFO] eclipse-repository ................... SKIPPED
    [INFO] ------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] -------------------------------------------
    [INFO] Total time: 50.430s
    [INFO] Finished at: Thu Apr 19 15:37:05 CEST 2012
    [INFO] Final Memory: 60M/143M
    [INFO] ------------------------------------------
    [ERROR] Failed to execute goal org.eclipse.tycho:tycho-packaging-plugin:0.13.0:validate-version (default-validate-version) on project org.holbreich.lf
    gm: OSGi version 1.0.0.SNAPSHOT must have .qualifier qualifier for SNAPSHOT builds -> [Help 1]
    Could You take a look of this problem?I think its problem between manifest.mf:bundle-version and pom.xml version.
    If i fix it, I come back here :)

  • dupas

    good post!!
    best regards

  • AlexH

    tostao thank you for your feedback.
    So
    mvn eclipse:eclipse
    is wrong. It will not bring my app to work.

    Do the following:
    mvn clean install
    on org.holbreich.lfgm.parent project.
    it schould buld everything. This Could take log because target platform and maven artefact will be downloaded.

    If this fails somehow then try to build
    org.holbreich.lfgm.target first. However normaly there is no need to do it separatelly.

    Feel free to as further questions.

  • Bob

    I want add appache-commons to project, in which pom add dependency?I would like use it in org.holbreich.lfgm.
    Best regards
    (
    org.apache.commons
    commons-lang3
    3.1

    )

  • AlexH

    Thank you for this very good question.
    Merging the OSGi/eclipse world to whatever maven is tricky.
    Tycho defines OSGi plug-in dependency system as leading system for dependency resolving.
    So i would say you can't and should not define dependencies through maven.

    To use a library you have at least two ways.
    1) The easies: you just include this library into the plug-in. In that case no additional configuration is needed outside of that plug-in. But this is not recommended way in sense of reusage of this lib and in a sense of clean code separation.

    2) The "cleaner" way is to use apache-commons (or whatever) are bundle. You can create bundles of "normal" jars directly out of eclipse (New->Project->Plugin from existing jar). This creates new bundle (Plug-in) which can be reference from another plug-in. Just repeat the configuration like one in org.holbreich.flgm.

    P.S. We could use maven to resolve dependencies of such libraries and automatically creation of bundles (See apache Felix). However you have to define the dependencies between the components of your RCP app manually again.

    Hope this answers your question.
    Fill free to refine your problem.

  • Fabian Piau

    Hi,

    Thanks for tip.

    So I am trying the second "cleaner" method, but when I run "mvn clean install" I got an error :

    org.apache.maven.InternalErrorException: Internal error: java.lang.RuntimeException: "No solution found because the problem is unsatisfiable.": ["Unable to satisfy d
    ependency from org.home.hellofab 1.0.0.qualifier to bundle org.home.hellofab.libs.collections 1.0.0.", "No solution found because the problem is unsatisfiable."]

    Assuming that org.home.hellofab is my test project which uses org.apache.commons.collections that I have bundle using eclipse wizard in org.home.hellofab.libs.collections 1.0.0.

    Any idea of what is wrong in my config?

  • yogen

    Sub: swt implementation fragment bundle error

    Hi,
    I am using maven3 and eclipse helios 3.6.
    I have imported the sample projects into my workspace and change target for helios instead of "indigo" at parent pom

    org.holbreich.lfgm
    target-platform
    1.0.0-SNAPSHOT
    helios

    and at target prject pom...

    helios.target
    target
    helios

    Thats all I have changes and execute mvn clean install..but I am getting "swt implementation fragment bundle" error.

    Please help me how to resolve this error.

    Please see error at console mentioned below.

    INFO: basic authentication scheme selected
    [ERROR] Internal error: java.lang.RuntimeException: Could not determine SWT implementation fragment
    bundle -> [Help 1]
    org.apache.maven.InternalErrorException: Internal error: java.lang.RuntimeException: Could not deter
    mine SWT implementation fragment bundle
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:168)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImp...:43)
    at java.lang.reflect.Method.invoke(Method.java:623)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
    Caused by: java.lang.RuntimeException: Could not determine SWT implementation fragment bundle
    at org.eclipse.tycho.p2.impl.resolver.ProjectorResolutionStrategy.fixSWT(ProjectorResolution
    Strategy.java:151)
    at org.eclipse.tycho.p2.impl.resolver.ProjectorResolutionStrategy.resolve(ProjectorResolutio
    nStrategy.java:110)
    at org.eclipse.tycho.p2.impl.resolver.P2ResolverImpl.resolveProject(P2ResolverImpl.java:102)

    at org.eclipse.tycho.p2.impl.resolver.P2ResolverImpl.resolveProject(P2ResolverImpl.java:69)
    at org.eclipse.tycho.p2.resolver.P2TargetPlatformResolver.doResolvePlatform(P2TargetPlatform
    Resolver.java:342)
    at org.eclipse.tycho.p2.resolver.P2TargetPlatformResolver.resolvePlatform(P2TargetPlatformRe
    solver.java:162)
    at org.eclipse.tycho.core.resolver.DefaultTychoDependencyResolver.resolveProject(DefaultTych
    oDependencyResolver.java:85)
    at org.eclipse.tycho.core.maven.TychoMavenLifecycleParticipant.afterProjectsRead(TychoMavenL
    ifecycleParticipant.java:91)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:274)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
    ... 11 more
    [ERROR]
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please read the following arti
    cles:
    [ERROR] [Help 1] http://cwiki.apache.org/con...

  • yogen

    Hi,

    How can I copy some folder from a outside folder to the product target folder. For example If I have created a product for windows my target in repository will look like this
    "eclipse-repository\target\products\com.gd.convego.assist.ace.product\win32\win32\x86"

    This the folder where I want to copy some folders from a directory which is outside the project folders say "C:/Mydata/folder1" "C:/Mydata/folder2" etc.

    How can I do this in given example of blog.?

  • yogen

    @Tostao

    you are getting this error bcz your anot having qualifier associated with your version info.

    your plugin or features' plugin.xml or mainfest file should have version like this
    "1.0.0.qualifier"
    not like this
    "1.0.0" or something.

  • AlexH

    Hi yogen,

    to you first question:
    have you defind the target file
    helios.target also? If yes, is it correct?

    to your second question:
    Why do you need to copy something (automaticaly on maven build?) to the product directory if it was not part of product or underlaying feature? Did i get your qustion right?

  • Lars Vogel

    Wrt. Athena the original creator of Athena has also switched to Tycho and this project is not maintained anymore.

  • AlexH

    Nice to know.
    Seems that tycho has future ;)

  • Steffen D

    Hey there,
     
    thank you for this tutorial, it helped a lot for the beginning. I'm trying to build the application directly via shell, via Jenkins and via Hudson. The first two solutions wirked without problems, but Hudson is giving me a NPE. (see http://pastebin.com/3VQjBHuz ) The same configuration worked with Jenkins, but neither with Hudson 2.2.1 nor with Hudson 3.0.0-RC4.
    I have no idea where this error comes from, but perhaps someone knows!?
     
    Thanks in advance,
    Steffen

  • AlexH

    Hi, the exception beginns with: "ERROR: Processing failed due to a bug in the code. Please report this to [email protected]        at hudson.FilePath.isAbsolute(FilePath.java:214)        at hudson.FilePath.<init>(FilePath.java:202)        at hudson.FilePath.child(FilePath.java:938)"
     
    and it clearly say that it is a Hudson bug... I'm not sure how well is Hudson supported now. Why not using Jenkins?
    @hudsonci

  • AlexH

    @Steffen D By the way now it works on Travise CI https://travis-ci.org/shuro...

  • AlexH

    @Steffen D By the way now it works on Travise CI https://travis-ci.org/shuro...