Using Tycho to Build an OSGi Project

I recently migrated the build process for an application from a monolithic Eclipse Buckminster build to a Maven build using Tycho.  Our source code was componentized and runs in an OSGi container, but our build was not, making it difficult to version each component individually.

Because all of our OSGi meta-data was already stored in the OSGi MANIFEST.MF files, we wanted a built process that would leverage that investment, while providing us the flexibility and functionality  a generalized build tool provides.  Maven and Tycho fit the bill.

Tycho is only supported on Beta releases of Maven 3.  We used Beta 2 for our build.  Tycho is simply installed as a build plugin, so all you need to get started is the Beta release of Maven 3.

The Maven/Tycho setup is pretty simple.  We defined a parent POM that provided the Tycho dependency, the child modules to build, and the P2 Update Sites that provided any dependencies needed by the component.  The Tycho part of the config looked like:

<build>
<plugins>
  <plugin>
    <groupId>org.sonatype.tycho</groupId>
    <artifactId>tycho-maven-plugin</artifactId>
    <version>${tycho.version}</version>
    <extensions>true</extensions>
  </plugin>
  <plugin>
    <groupId>org.sonatype.tycho</groupId>
    <artifactId>target-platform-configuration</artifactId>
    <version>${tycho.version}</version>
    <configuration>
      <resolver>p2</resolver>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.sonatype.tycho</groupId>
    <artifactId>maven-osgi-packaging-plugin</artifactId>
    <version>${tycho.version}</version>
    <configuration>
      <format>'${build.qualifier}'</format>
    </configuration>
  </plugin>      
</plugins> 
</build> 

We used Tycho version 0.9.0 for our build.  The build.qualifier allows a Source Control revision number or other number to be used for SNAPSHOT or incremental builds.  This value replaces the .qualifier part of the OSGi version number string.

For each component we use the 'package' Maven build command, which produces an P2 Update Site.  When other components have dependencies on a component, it references its update site in the parent pom file.  This looks something like this:

<repositories>
  <repository>
    <id>newco-core</id>
    <url>http://updatesite.newco/dev/component/branch</url>
    <layout>p2</layout>
  </repository>
</repositories>

This allows us to version and build each component individually.  We can then mix/match the P2 Update Sites that are created to produce custom aggregate sites that can be tailored as needed.  We currently used the P2 Mirror Ant task to produce the composite sites.

The pom file for each OSGi module or feature is trivial.  It is just a reference to the parent project, and the type of OSGi module that it is.  Here is a sample:

<?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>
  <parent>
    <artifactId>myComponent</artifactId>
    <groupId>com.ericdaugherty</groupId>
    <version>1.0.0-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
  </parent>
  <groupId>com.ericdaugherty</groupId>
  <artifactId>com.ericdaugherty.myComponent</artifactId>
  <version>1.1.0-SNAPSHOT</version>
  <packaging>eclipse-plugin</packaging>
</project>

So now we can build each of our 'components' individually, without making a change to our development process.  Our development teams continue to maintain the configuration and dependencies in the OSGi MANFIEST.MF files.

We ran into a few bumps in the road along the way, but were always able to resolve it in a way that both Eclipse and Tycho accepted.

Overall, I'm very happy with the result.  We can now compile a wider range of projects (including Scala) that we could not build before with Buckminster, and have much more fine grained control.