Mattias Holmqvist – Writings about software development

When you want to work effectively with Maven/Tycho on a larger project, you quickly find yourself wanting more features than the simple build presented in my previous posts. In this post i will cover some important features of Tycho that you might need to work more effectively with Tycho.

I suspect this post will be quite massive so I’ll skip the screenshots in this one. Instead I decided to create a sample project structure and put it up on my github account. See the readme for information on how to set up the example projects.

Overall structure and idea

The parent project (with .parent suffix) is the mother of the build. Practically all configuration of the build is handled by its pom.xml file. We strive to keep the sub-projects as small as possible to minimize the duplication of information in the development environment (Eclipse in this case) and the headless build system (Tycho/Maven).

The information that we’re required to provide in the sub-projects’ pom.xml files are the version of the project (which is verified against the version provided in the Manifest.MF) and the type of project (feature/bundle/test bundle/update site).

I will describe the things that I reckon is most important in the example projects so that you (hopefully) can follow what’s happening when building the projects.

Features and update sites

The sample project contains a feature project and an update site project. These two projects are intended to give some extra help from within the Eclipse IDE. When the plugins are built by the CI server (I assume you have one!?), the server can also push the update site (containing the feature) to an HTTP server (or similar) that is available for developers that want to use the plugins as target platform in their development. This makes the build quite modular and nice to work with.

Tycho makes the automation for building for your features and update sites quite a simple task. You need to create a pom.xml for your feature looking somewhat like this:

<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>se.mattiasholmqvist</groupId>
    <artifactId>examples</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <groupId>se.mattiasholmqvist</groupId>
  <artifactId>examples.feature</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>eclipse-feature</packaging>
</project>

Note: See the sub-project with .feature-suffix for the provided example.

This pom file is very similar to the bundle pom file. The only difference is the <packaging> tag that tells Tycho to build the project as a feature. The nice thing about these tiny poms is that the dependency management becomes quite easy. You can more or less work without caring about the Maven configuration since Tycho uses the Manifest and feature.xml to setup the correct build dependencies.

Of course, you would also need to specify a proper target platform. In my previous posts, I’ve shown how to do this with the -Dtycho.targetPlatform switch, which works but there is a cooler and more flexible way that also works great with Tycho.

Target platform definitions

Ok, we have our build set up nicely and all seems to be working fine. However, the great success of your project has made it grow significantly and it seems that not all developers that join the project are able (or willing) to setup their target platforms (in Eclipse) in accordance with the Tycho build since it requires quite a lot of understanding about Tycho/OSGi and perhaps Eclipse P2 as well. This causes disturbance to your project and you do your best to help your teammates out, but you reckon there must be a better/simpler way of tackling this issue than to manually manage the target platform installation for each developer.

A short tale about the target definition file

The target definition file is quite a newcomer to the Eclipse development environment. It is a nice feature that lets you specify the target platform in a structured fashion (although the previously supported directory-based platforms are still supported in Eclipse) which I highly recommend. Another even nicer thing is that Tycho also supports resolving the target platform from the Eclipse target definition file. This means that setting up the development environment for a new developer in simply a matter of locating the target definition file and click on “Set as target platform”, and the target platform is now consistent with the platform that Tycho uses. This is probably not a perfect description but you can find some more info from the Eclipse help and some more info on using them in practice can be found here.

The first step – creating the .target file

I like to keep my target platform in a separate project, just for structure and separation. My guess is that you can make it work by putting it anywhere you want, but in my example I’ve put it in the project called se.mattiasholmqvist.tychoexamples.targetplatform.

I’ve created a target definition file in Eclipse (it’s found in the New-> menu) and I’ve called this file example_target.target and placed it directly in the target platform project directory. I selected a few Eclipse dependencies that I needed for my bundle and saved the file.

We also need to provide some configuration to this project. I’m not sure if this is the only way to do this at the time of writing but I’m sure that it works for me. This is a snippet from the pom.xml that I use for the target-platform project:

<build>
  <plugins>
    <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>example_target.target</file>
                <type>target</type>
                <classifier>example_target</classifier>
              </artifact>
            </artifacts>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Testing

Tycho supports unit-testing (JUnit) of code within bundles by default. This has long been a hazzle (for me atleast), when working with Ant + PDE  build so this support is extremely welcome. Tycho tests bundles via the integration-test Maven goal, which is different from the regular test goal. It also makes life easier if you know a bit about the conventions Tycho uses for finding tests (this might however be subject to change in the future).

Start by creating a simple bundle that will contain the classes of your application. Second, we will create a separate bundle that will contain our tests. The convention here is to use the same same as the bundle with your application classes and add the prefix .tests to the test bundle name. I provide a (really stupid) test in the project with .tests-suffix in the github repo.

Note: The Test suffix is important if you want to use the default configuration of Tycho, or it won’t find your test class. Below is a snippet from the configuration of the test plugin for my example projects which enables unit testing for the project:

<packaging>eclipse-test-plugin</packaging>

I also made the .tests project a fragment to the bundle it belongs to. This makes it easier to locate classes to depend on. I think this setup works well within Eclipse/OSGi development.

Code coverage using EclEmma

Using code coverage in an OSGi environment is special. There are however some Eclipse plugins that support code coverage and it is possible to integrate these with Tycho. I want to give credit to the guys at Sonatype for helping me out with this. They recently posted some information on their website related to code coverage, so my example project might serve as a good complement to this article. I thought it might be a good idea to wrap our discussions up in an example that is perhaps a bit more accessible than the posts on the mailing list. My example is however a bit more simplistic than the example in the article above. I do not copy resources from multiple test bundles, but instead generate a report for each bundle. Check out the article if you need that feature.

In large, the code coverage is handled by a Maven profile so you need to pass a -Pcoverage flag to enable it.

To run the test suite (1 test in the example project) with code coverage and reporting:

mvn integration-test verify -Pcoverage

In my examples project I’ve put together a small bundle project that contains Eclemma Equinox runtime. It would probably be possible just to deploy it to a locally accessible Maven repository but for ease of use of the examples I’ve made it a part of the build instead. When you run mvn integration-test with the coverage profile in the parent project directory, this bundle will do code coverage of all bundles/packages that matches the configuration in the parent pom.xml. See the <profiles> configuration in the parent- and test project pom.xml files for exactly how this is done.

Hope this post can help someone out there with use Tycho which is a great tool for your OSGi development.

Checkout Sonatype’s Tycho website to keep up-to-date with the development of Tycho.

Building RCP applications (products) have always been quite smooth when working from within Eclipse IDE. To me, it is extremely important that the development team can easily build their product and have continuous integration of the product on a CI server such as Hudson.

Previously, PDE build have been the way to build RCP applications in a headless build environment (such as Hudson, for example), but all those Ant scripts and configuration options in the build.properties file are not that appealing to me.

Tycho provides support for building RCP applications from product configuration files. As we will see, this makes the headless build for RCP applications a lot less confusing.

One nice thing that I forgot to mention about Tycho in my previous post is that is has great support for Manifest-first development. This means that the development team does not need to synchronize their Manifest files with the pom.xml that Tycho uses, it is handled automatically for them. The developers can use “Imported packages” and “Required plug-ins” as usual and Tycho will use that information to resolve the compilation target for each bundle. I find this workflow easier and more appealing than pom-first development (for example BND-plugin with a separate .bnd file for configuring exported/imported packages). I guess you have to figure out which way works for you.

This might not be as appealing for some of you who are accustomed to specifying Maven dependencies in the pom.xml but Tycho supports pom-first development as well. However, since I like to work Manifest-first I will use it for my examples here. For info on pom-first development, check out the Tycho users mailing list or the official website.

This will be a quick intro on how to get started with a small Eclipse RCP application in Tycho. The first steps involves creating the setup of one plugin/feature/product so you who are Eclipse-wise don’t need to follow these steps thoroughly.

Note: This post will assume Tycho 0.7.0 and Eclipse 3.5.2. Some of the issues in this post will probably be fixed in upcoming releases of Tycho. Hopefully the main workflow will remain somewhat steady. I will also only provide examples for the explicit target platform resolver. The implicit p2 resolver should work just as fine, check out the previous post to see how to set it up. I will also not include all configuration options that are available for Tycho, but please comment if you miss something and I might add it later!

Let’s build an application!

Creating the application plug-in

Start by creating a plug-in that defines our RCP-application. There are some templates ready for creating example RCP application in the Eclipse distributions. I used the “Hello RCP” template which contains a simple application saying “Hello RCP” in the title bar. See the screenshots below for how I created my example plugin.

Creating the application feature

Products in Eclipse can either be plugin-based or feature-based.  We will build a feature-based application so we start by creating a project that will contain the main feature for our RCP application. The feature contains a feature.xml, which is used to define which plug-ins constitutes the feature. When asked for plug-ins to include in the feature, reference the plug-in that we created in the first step.

The feature will be referenced by the product definition, which tells Tycho to use it when constituting the product.

Configuring the product definition

We need to create the product definition that constitute our product. This will include the feature project that we created previously and the Eclipse RCP feature. Pay attention to the naming of the product definition file since Tycho uses the convention that the file name should match the maven module with a .product suffix.

Start by creating a new project (I prefer keeping the product file in a separate project).

New project

Name the project so that it matches your product in whatever way you find appropriate. I named my project se.mattiasholmqvist.rcpexample. Tycho now assumes that my product definition file is name se.mattiasholmqvist.rcpexample.product

We create our product configuration file and add it to our product project.

Choose an ID and a name for the product and make sure that you set your product includes native launcher artifacts.

We need to create a new product definition. This definition refers to the application extension that our application plug-in defines (this comes from the RCP template).

You need to specify which features constitutes the product. Since we build an Eclipse RCP product you need to include the RCP feature (org.eclipse.rcp) and the feature that we created earlier which contains our application-defining plug-in. Make sure that the definition specifies that the product is build using features.

Setting up the build files

From our workspace location, we can now generate a parent pom.xml together with a pom-file for the plug-in project we just created. Fire up your command line and generate the pom-files.

mvn3 org.sonatype.tycho:maven-tycho-plugin:generate-poms -DgroupId=se.mattiasholmqvist -Dtycho.targetPlatform=/Users/mattias/dev/eclipse-3.5.2-delta/

This goal is typically run only once since you don’t want to replace any changes you’ve made to the parent pom. I use only the parent pom to add plug-ins to the build. I’m not sure if that’s the way to go but it seems like a good idea that the individual plug-in projects has minimum-sized pom files that we don’t need to change that often.

You don’t actually need to run <code>generate-poms</code>. This maven goal is only used to bootstrap the build by creating the initial pom files so you don’t need to create these files yourself initially. If you have a parent project with many plug-in projects this might be quite useful. If you want more control over what’s happening, just copy & paste the pom.xml files I created (shown below) and modify them to your need.

This renders a parent pom.xml that looks something 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>
  <groupId>se.mattiasholmqvist</groupId>
  <artifactId>rcpexample-parent</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <build>
    <plugins>
      <plugin>
        <groupId>org.sonatype.tycho</groupId>
        <artifactId>tycho-maven-plugin</artifactId>
        <version>0.7.0</version>
        <extensions>true</extensions>
      </plugin>
    </plugins>
  </build>
  <modules>
    <module>se.mattiasholmqvist.rcpexample.feature</module>
    <module>se.mattiasholmqvist.rcpexample.plugin</module>
  </modules>
</project>

As we can see this does not contain a module for the product project that we created earlier. Tycho cannot understand that our product project defines a product, but that’s a minor thing. We should add the product project to the parent pom.xml so that the modules section looks like this:

<modules>
  <module>se.mattiasholmqvist.rcpexample.feature</module>
  <module>se.mattiasholmqvist.rcpexample.plugin</module>
  <module>se.mattiasholmqvist.rcpexample</module>
</modules>

We also need to create a pom.xml in the product project that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>se.mattiasholmqvist</groupId>
    <artifactId>rcpexample-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <groupId>se.mattiasholmqvist</groupId>
  <artifactId>se.mattiasholmqvist.rcpexample</artifactId>
  <version>1.0.0</version>
  <packaging>eclipse-application</packaging>
</project>

Note the eclipse-application packaging in the pom. This tells Tycho that the project is actually an RCP application and Tycho starts looking for a product definition file during the build.

Installing the delta pack in the target platform

To build applications that depend on platform-specific parts of the Eclipse SDK (such as SWT), we need to provide a target platform that contains the Eclipse Delta pack. There are multiple sources on the web that describes how to install the delta pack so look at for example this site or this one.

Building the product

We are now ready to build our product.

mvn3 package -Dtycho.targetPlatform=/Users/mattias/dev/eclipse-3.5.2-delta/

This should build your product and place an executable application under /target directory in your product project. There are however currently some issues that you might run into depending on your build environment/target platform.

The import org.eclipse.swt.graphics.Point cannot be resolved.

You might run into something like this:

[ERROR] Failed to execute goal org.sonatype.tycho:maven-osgi-compiler-plugin:0.7.0:compile (default-compile) on project se.mattiasholmqvist.rcpexample.plugin: Compilation failure: Compilation failure:
/Users/mattias/dev/projects/tychoexamples/clean/se.mattiasholmqvist.rcpexample.plugin/src/se/mattiasholmqvist/rcpexample/plugin/ApplicationWorkbenchWindowAdvisor.java (at line 1):[-1,-1]
	package se.mattiasholmqvist.rcpexample.plugin;
	^
The type org.eclipse.swt.graphics.Point cannot be resolved. It is indirectly referenced from required .class files

/Users/mattias/dev/projects/tychoexamples/clean/se.mattiasholmqvist.rcpexample.plugin/src/se/mattiasholmqvist/rcpexample/plugin/ApplicationWorkbenchWindowAdvisor.java (at line 3):[-1,-1]
	import org.eclipse.swt.graphics.Point;
	       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
...

This is a problem with Tycho not knowing which native environment to build for. Tycho needs this information to find the correct SWT fragment in the target platform. The expected default behaviour would be that Tycho looks for a fragment that is supported by the system running the build but currently there are some issues with MacOS X (which I use). However, this issue will be fixed in release 0.8.0 of Tycho.

So, we need to provide this information to Tycho somehow. In my case, I want to build for MacOS X, Cocoa windowing system and the x86 architecture. We have three options (that I know). We can provide these properties on the command line, in the Maven settings.xml or in the pom.xml directly.

On the command line it looks like this:

mvn3 package -Dtycho.targetPlatform=/Users/mattias/dev/eclipse-3.5.2-delta/ -Dosgi.os=macosx -Dosgi.ws=cocoa -Dosgi.arch=x86

In the pom.xml (or the settings.xml for that matter):

<properties>
  <osgi.os>macosx</osgi.os>
  <osgi.ws>cocoa</osgi.ws>
  <osgi.arch>x86</osgi.arch>
</properties>

Missing target environment
This might also be a problem:
[ERROR] Failed to execute goal org.sonatype.tycho:maven-osgi-packaging-plugin:0.7.0:product-export (default-product-export) on project se.mattiasholmqvist.rcpexample: Product includes native launcher but no target environment was specified -> [Help 1]

Which is due to the fact that the Tycho packaging plugin needs configuration to know which target environment to build the product for. We can solve this by adding the following to the plugins section of the parent pom.xml:

<plugin>
  <groupId>org.sonatype.tycho</groupId>
  <artifactId>maven-osgi-packaging-plugin</artifactId>
  <version>0.7.0</version>
  <configuration>
    <environments>
      <environment>
        <os>macosx</os>
        <ws>cocoa</ws>
        <arch>x86</arch>
      </environment>
    </environments>
  </configuration>
</plugin>

We’re done, let’s start the application!

Open the target directory of your product project (in my case se.mattiasholmqvist.rcpexample/target) and you should find an executable RCP application. In my case (since I’m on a Mac) I found a rcpexample.app in my target directory. Behind this file is this beautifully built, and extremely useful application:

That’s it for building a simple Eclipse RCP app with Tycho. Good luck!

As a reminder, please check out the Tycho users mailing list. Help the people at Sonatype out with feedback on their project.