Building p2-enabled products with Tycho

Posted by Kai Kreuzer on December 1, 2010
Working on the build and the packaging of openHAB, I had to undergo quite some efforts to get it done with Maven3/Tycho.

My special challenge was to package a product which is p2-enabled and includes root files. If you just want to do the one or the other, it works quite straight forward: You can use the "eclipse-application" Tycho packaging type to build Eclipse RCP products, which will also nicely include any root files that you have defined on your features.

Since version 0.10.0, Tycho also supports building p2-enabled products (TYCHO-188), but you will have to use the "eclipse-repository" packaging type to do so. Unfortunately, root file inclusion does not work with this packaging type (due to very complex reasons, see TYCHO-513 and TYCHO-465).

So what is the workaround to have both at the same time? I have chosen a combination of the "eclipse-repository" packaging and the "classic" Maven assembly plugin to do this job.

The "eclipse-repository" packaging is used in a Maven project that contains the RCP product definition. Using the "materialize-products" and "archive-products execution, makes sure that the p2 director is used to install and package a product from the repository (for all platforms that are listed in the configuration of the target-platform-configuration Maven plugin). Note that choosing Mac as a platform does not seem to be an option right now, at least I could not get it working...

If you now run a "mvn clean install" on this project, you will find the resulting zip files in the target folder. But how to add additional files (such as readmes, licenses, start scripts, additional libraries and folders, etc.) to it to make it your final distribution? That's where the Maven assembly plugin comes into play:

You need to create a Maven project that contains the files you want to add. The assembly plugin allows the inclusion of project dependencies in the assembly, so we need to define a dependency on our product project in our pom.xml. The problem here is that if you do this as usual, you will end up with the packaged p2 repository to be included in your assembly as this is the primary artifact built by the "eclipse-repository" packaging. Luckily, the product zips are attached as additional artifacts to the build result, so we can define a dependency like:
<dependency>
<groupId>com.acme</groupId>
<artifactId>com.acme.rcp.product</artifactId>
<version>${project.version}</version>
<type>zip</type>
<classifier>win32.win32.x86</classifier>
</dependency>

In the assembly descriptor, you then need to say that you want to unpack this dependency into your assembly. As Tycho often packages a bit to much into the zips, you can also take this opportunity to remove a few contents that you do not want in your final distribution:

<dependencySets>
<dependencySet>
<useStrictFiltering>true</useStrictFiltering>
<useProjectArtifact>false</useProjectArtifact>
<useTransitiveDependencies>false</useTransitiveDependencies>
<outputDirectory>/</outputDirectory>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>**/org.eclipse.platform.doc*.jar</exclude>
<exclude>**/org.eclipse.jdt.doc*.jar</exclude>
</excludes>
</unpackOptions>
<includes>
<include>*:org.openhab.designer.product:*:win32.win32.x86</include>
</includes>
</dependencySet>
</dependencySets>
Note the reference to include (only) the dependency to the zip for the Windows platform; this is necessary as you might have many dependencies for different platforms defined in your assembly pom.xml. This include tag makes sure that this assembly descriptor picks up the right dependency (you can have other assembly descriptors for other platforms in the same assembly project).

This solution might not be the most elegant, especially if you are building packages for many different platforms (you need a separate assembly descriptor for each). But it works for me and I thought it could be helpful to others as well. If anybody knows a smarter solution or has a suggestion how to improve mine, I'll be more than happy to listen :-)