Tuesday, 1 April 2008

Taking the pain out of Eclipse RCP builds and exports

It is well worth reading the manual, as the old saying goes - but sometimes the manual can be misleading, especially if the software being documented has evolved since it was written.

Eclipse Help

If you're using Eclipse 3.3, the advice in the 2006 edition of The Book about enabling Help in your Eclipse RCP applications is no longer quite accurate. Section 13.2 ("Getting the Help Plug-ins") tells you to install lots of things, while my experimentation has shown that all you need are the following plug-ins in your target platform and any launch configuration, plus their dependencies:
  • org.eclipse.help.ui
  • org.eclipse.help.webapp
You will also find this information in the built-in help provided with Eclipse RCP Developer under Platform Plug-in Developer Guide -> User assistance support -> Help -> Configuration/setup -> Rich Client Platform (RCP) help. On discovering it, I felt a little like Arthur Dent finding the planning application for the bypass through his house (look for the telling phrase "Beware of the Leopard")! Interestingly, the on-line version of the same help page disagrees - listing a lot of superfluous plug-ins - which confused me for quite a while.

The dependencies, all of which you can copy from the plugins folder of your Eclipse installation to your target platform, are as follows:
  • org.eclipse.help.base
  • org.apache.jasper
  • org.apache.lucene
  • org.apache.lucene.analysis
  • org.eclipse.equinox.http.jetty
  • org.eclipse.equinox.http.registry
  • org.eclipse.equinox.http.servlet
  • org.eclipse.equinox.jsp.jasper
  • org.eclipse.equinox.jsp.jasper.registry
  • org.eclipse.osgi.services
  • javax.servlet
  • javax.servlet.jsp
  • org.mortbay.jetty
  • org.apache.commons.logging
  • org.apache.commons.el
Also, to use Eclipse Help successfully under Windows (and that includes your own help for exported / launched applications), you have to have your Internet Explorer preferences set up to use no proxy server when accessing localhost / 127.0.0.1. One way to do this in Internet Explorer's Tools -> Internet Options -> Connections -> LAN Settings is to turn off all three main check boxes. You could also try setting the "auto detect settings" checkbox or the manual proxy server configuration (provided you also check the "bypass proxy server for local addresses" checkbox).

Editing and Debugging

For some things, Eclipse needs source plug-ins to be present in the target platform location, not just in the installation location.I have not yet established all the circumstances under which this may be the case, but I have found that if you are trying to use the special-purpose editor to work on a plugin.xml file, unless the source plug-ins are present in the target platform location, when you right-click on an extension point in the Extensions tab you won't see the correct extension types in the context menu (just "Generic").

To support the most common types of UI extension, such as menu entries, copy the source plug-ins for org.eclipse.platform and org.eclipse.rcp from your Eclipse plugins folder into the target platform (hint: they are folders!). It is not even necessary to select them when specifying the target platform in Eclipse Preferences, but does no harm.

Source organisation

It turns out that the line of least resistance is to separate your plug-ins and features into two groups:
  • All the stuff you have access to in source form directly from its repository
  • Everything else - basically the Eclipse and third-party stuff
The second category forms your Eclipse RCP target platform, which should be a minimal Eclipse RCP installation plus all the features and plug-ins and their dependencies that you need in your application, plus source plug-ins where available. I created a target platform initially by downloading the RCP Runtime Platform plus Delta Pack (version 3.3.1.1, which matches the version of Eclipse RCP Developer I was using), but then deleted a lot of things that were not relevant to my intended deployment architecture before adding the plug-ins and features I really needed (see above).

For the first category, I recommend setting up your source folder structure to match the output in the build directory.
  • product root
    • features
      • a.b.c.d.feature
      • etc.
    • plugins
      • a.b.c.d
      • a.b.c.d.product
      • a.b.c.d.update-site
      • etc.
It helps if you append "feature", "product" or "update-site" as the last component of the folder name, as appropriate, where a folder contains something other than a plug-in. Once each of these has been turned into an Eclipse project in your workspace, they will simply appear as a linear alphabetically ordered list in the package explorer, so this helps you to navigate.

Ignore the features supplied with the Eclipse SDK, RCP Runtime and Delta Pack. Instead, define your own features to include just the plug-ins on which your application depends. It helps to factorise this into a half-dozen features that collect Eclipse plug-ins for various capabilities - e.g. the feature com.example.myproject.help.feature could be used to list all the plug-ins shown above that are needed to provide application help. Then if you want to include help with an application, all it has to do is list this feature in its application feature.xml as an included feature (of course you still have to write the help texts and create a help plug-in to contain them!).

Version numbering

In product.xml and feature.xml files, it is a good idea to set the version numbers of included plug-ins and features to 0.0.0 (or a range, where applicable) to ensure that the latest version is always used during the build - the exported feature.xml files will end up containing the resolved version numbers.

2 comments:

Unknown said...

I've spent the past day or so experimenting with getting my target working with pde headless build. I'd more or less come to the same conclusion regarding the required packages as you have (Delta pack, RCP binary and the packs you've listed).

However, once they're all in PDE starts asking me for all kinds of strange things, not least:

[java] [eclipse.generateFeature] Bundle org.eclipse.platform.source.linux.gtk.x86:
[java] [eclipse.generateFeature] Host plug-in org.eclipse.platform.source_3.3.3.r33x_r20080129-_19UEl7Ezk_gXF1kouft has not been found.
[java] [eclipse.generateFeature] Bundle org.eclipse.rcp.source.linux.gtk.x86:
[java] [eclipse.generateFeature] Host plug-in org.eclipse.rcp.source_3.3.3.r33x_r20080129-8y8eE9UEUWI6qujeED0xT7bc has not been found.

And:

[java] /usr/lib/eclipse/plugins/org.eclipse.pde.build_3.3.2.v20071019/scripts/productBuild/productBuild.xml:51: Unable to find plug-in: org.eclipse.debug.core. Please check the error log for more details.

After following this train for a while, all I seemed to be doing was taking all of my IDE plugins and dropping them into my target. Is this something you encountered?

Immo Hüneke said...

Generally I end up with just over 100 plug-ins in the target platform. I think the IDE has over 200, so it can't be everything.

I do agree that constituting your target platform is a very tedious process at first. It can be short-circuited somewhat by using the Eclipse installation directory as your target temporarily. While in this configuration, create a new launch configuration for your application by clicking "synchronize" and then "launch an Eclipse application" in the Product Overview tab. Edit the launch configuration, delete all plug-ins and add required plug-ins. You'll probably notice that some are still missing (they might have been optional in some manifest), so tick those and add required plug-ins again. The resulting list of plug-ins should tell you which set you need in your target platform.

We've moved away from this system to a bottom-up approach, in which we group Eclipse plug-ins into features and then build a target platform on the fly by using the Maven dependencies (which we obviously have to arrange to mirror the product-feature-plugin dependencies). I developed a subclass of the maven dependency plugin, which understands how to copy / unpack features and plug-ins to the target platform.