Since its release, the Eclipse Rich Client Platform (RCP) has suffered from a lack of support for automated builds with tests. The IDE provides tools for building and packaging RCP applications, but they are very different from the PDE/Build tools that perform these tasks in an automated fashion. Also, until recently, testing support for JUnit 4 was not present in the Eclipse TestFramework. While the situation has markedly improved in Eclipse 3.6, setting up an automated build with tests remains a time-consuming and difficult task.
To make the job easier, I've created a minimal project called "Lightning," which demonstrates how to combine the new automated build tool Buckminster, the Eclipse Test Framework, and the integration testing tool SWTBot. Lightning has been tested on Linux and Windows. (Buckminster on the Mac platform has a few kinks to work out.)
Loading Lightning
Buckminster is a build system for Eclipse products and plug-ins. It can be run from within the IDE (with the proper tooling installed) or from the command line. I use the command-line version in Lightning, so no additional IDE tooling is required. Buckminster can inspect artifacts such as plug-ins and features in order to determine their dependencies.
I launch Buckminster with Apache Ant, which manages all the other tools required by Lightning. Ant provides the top-level targets and everything you need to run the build from Eclipse, the command line, or a continuous-integration server like Jenkins.
Since the command-line distribution of Buckminster is hard to install manually, the Lightning build process installs it automatically using the P2 director application from the Buckminster download site. P2 is the provisioning system in Eclipse, replacing the old update manager.
The first step in building the Lightning project is to download it from github and unzip it, or just clone the project using git.
Because this build uses Buckminster, you can actually download and assemble the target platform for the project from the Helios P2 repository automatically which is called "materializing" in Buckminster parlance. To do so, simply navigate to the "Buckminster.build.feature" directory and run the command ant materialize.target.platform, which will materialize the target platform to "<unzip location>/workspace-target-platform." This directory will serve as the target platform for the IDE workspace. Next, import the Lightning plug-ins into a new Eclipse 3.6 workspace and instruct it to use the target platform you just materialized.
Building the Application
You can kick off the full build process by running the command ant from the "buckminster.build.feature" directory.
The build process starts by installing P2. This, in turn, installs the command-line version of Buckminster. The next step uses Buckminster to build the Eclipse RCP products. Two products are created during the build process. The first is the test product, which includes Lightning along with all tests and test dependencies. The second is the production product, which includes only the Lightning application. This is the version that will be shipped to customers when the time comes. If it seems a little strange that two products are needed, just remember that the tests must be run inside an OSGi environment, and this means that they need to be packaged into a fully functional Eclipse RCP application.
When Buckminster is used to build the Lightning products it runs in an Eclipse workspace, just as it would if it were being run from within the IDE. The first step in building the product, therefore, is to set up the workspace and associated target platform. This gives Buckminster a sandbox in which to play. The target platform is imported using a target definition file, which tells Buckminster where to place any plug-ins it later downloads for the target platform. Next, the import command executes an import of those plug-ins as defined in a .cquery file (Listing One).
Listing One: The structure of the .cquery file.
<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="target.platform.rmap">
<cq:rootRequest name="buckminster.build.feature" componentType="eclipse.feature"/>
...
</cq:componentQuery>
The .cquery file points to an Eclipse feature that I have created especially for Buckminster, and also includes a list of places to find the plug-ins included in that feature. This list is stored in an .rmap file, part of which I include in Listing Two.
Listing Two: The .rmap file.
<rm:rmap xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0"
xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0">
<rm:searchPath name="helios">
<rm:provider componentTypes="osgi.bundle,eclipse.feature"
readerType="p2" source="false" mutable="false">
<rm:uri format="http://download.eclipse.org/eclipse/updates/3.6" />
</rm:provider>
</rm:searchPath>
<rm:searchPath name="local-repository">
<rm:provider componentTypes="osgi.bundle,eclipse.feature"
readerType="p2" source="false" mutable="false">
<rm:uri format="{0}local-repository">
<bc:propertyRef key="build.feature.dir.url" />
</rm:uri>
</rm:provider>
</rm:searchPath>
<rm:searchPath name="local-source">
<rm:provider componentTypes="osgi.bundle,eclipse.feature"
readerType="local" source="true" mutable="false">
<rm:uri format="{0}{1}">
<bc:propertyRef key="product.checkout.url" />
<bc:propertyRef key="buckminster.component" />
</rm:uri>
</rm:provider>
</rm:searchPath>
<rm:locator searchPathRef="local-source" failOnError="false" />
<rm:locator searchPathRef="local-repository" failOnError="false" />
<rm:locator searchPathRef="helios" failOnError="false" />
</rm:rmap>
The .rmap file lists the locations of the plug-ins that ultimately make up the application. These include public P2 repositories from the Internet, local P2 repositories, and local source folders. The local P2 repositories were created earlier in the build process using the P2 director application and a list of previously built plug-ins. To reduce traffic to the remote P2 repositories, it is a good idea to create mirrors of the P2 repositories on the local network (though this is not required).
Once the .cquery is imported, Buckminster has a fully materialized target platform, a workspace, and the required projects for Lightning. It is now ready to build the projects. Note that you could set up the build to use the workspace-target-platform created earlier, and the process would probably be a bit faster. But I wanted to demonstrate how Buckminster can assemble a target platform on the fly.


