Wednesday, July 08, 2009

ADT Part 2: More like the EPP

Yesterday, I posted an example of how to compose a product made up out of updatable sub-components. The first question there was about how this relates to the packages built by the EPP. The EPP packages are just products, much like my ADT. They use their own feature and plugin to brand the Eclipse package and do things like open a different default perspective.

The EPP packages are built slightly different from my first example. They use feature requirements to get version ranges for the sub-components, but they don't currently perform the extra director calls to make those sub-components into updatable roots.

Here is another example that is structured a bit more like the EPP packages.
This example is also available in cvs with the first (dev.eclipse.org:/cvsroot/eclipse/pde-build-home/examples/adt.feature.builder).

[Edit 2013/07/03: Eclipse CVS has migrated to git starting in 2010.  The examples are now available under the examples folder in http://git.eclipse.org/gitroot/pde/eclipse.pde.build.git. The example has not been updated to work with git and may require modifications.]

Features instead of p2.inf


In our first example, we used a p2.inf file to add requirements with version ranges to our product. I did it this way because I didn't have anything to add to the product, and didn't want to bother creating a feature.

Perhaps a more familiar way of doing things would have been to use a feature. So we create a feature "adt.feature", and instead of including our sub-components, we require them using a "compatible" match rule:



I also made my feature include the "org.eclipse.platfom" feature. The adt.product file then just includes adt.feature. We no longer need the p2.inf to add requirements to our product.

Adding Branding


Since we created our own feature for this product, we may as well take the next step and add our own branding plug-in. The first thing I did way create my own product extension in the plugin.xml:
    <extension id="product" point="org.eclipse.core.runtime.products">
      <product application="org.eclipse.ui.ide.workbench" name="ADT Product">
         <property name="aboutText" value="Andrew's Development Tools"/>
         <property name="windowImages" value="icons/icon.gif"/>
         <property name="aboutImage" value="product.gif"/>
      </product>
   </extension>


Note that the word 'product' here is slightly overloaded. There is a 'org.eclipse.core.runtime.products' extension point that defines branding for eclipse, and there is the product itself which is what we are building using the .product file.

This product is just running the normal workbench application, but it uses my own icons and images. We then change our adt.product file to use adt.plugin.product instead of the org.eclipse.platform.ide product extension we were using before.

In my adt.feature I set the branding plug-in to be my new adt.plugin. I also provide the normal about.* files so that my feature shows up in the about dialog.

As a final touch, I made my own splash screen.

Building the new Product


The build script is essentially unchanged from the first example. So I won't bother explaining the details again. The only difference is that I made some minor changes to the builder's build.properties file so that pde.build can find our feature and plugin.



Note that PDE/Build does not follow feature requirements when performing a build and publishing metadata. This means that for the director install to work, you need to have pre-existing metadata for the things that you are requiring. This same requirement exists with the first example where we used a p2.inf file.

22 comments:

Jacek Pospychala said...

Thanks Andrew. Your insights on productization are always priceless.

If there only was a simple Wizard to do all this wiring between features, plugins, products, metadata and IUs.

Kim Moir said...

I think there's a cron job that updates the viewcvs content, not sure how often it runs...

Chris Aniszczyk (zx) said...

Jacek, if you stick with using product definitions, things work pretty well. If you have any ideas on how to make things better, please file bugs or give a shoutout on the pde-dev mailing list ;)

Ian Mayo said...

Hi Andrew,
thanks for taking the time to document this important subject.

One question: how do you specify that your product will accept a range of feature versions that were specified in the p2.inf file in yesterdays article.

I'm trapped in the situation where my product won't accept updates because of dependencies on fixed verions - and hoping your articles will help me move forward...

CC said...

Andrew, in your new example you "include" the platform feature in your top level ADT feature. What happen if you don't include the platform but add it to the dependency list (together with CDT, CVS)?

I run into situation that if I don't include the platform feature in my top level feature, my final product does not have the "configuration/org.eclipse.equinox.simpleconfigurator" directory and no bundles.info file. The product fails to launch.

Andrew Niefer said...

The product here doesn't include the sub-components directly. Instead it is including the adt.feature.

It is this feature that requires the sub-components. Features have either inclusions ("Included Features" tab in the editor), or requirements ("Dependencies" tab). Inclusions are on specific versions and requirements are on version ranges.

In the example, the requirement of org.eclipse.cdt version 6.0.0 with match rule Compatible, is translated by p2 into a version range of [6.0.0, 7.0.0).

Unfortunately you can't specify the version range directly in the feature.xml, you can only use the match rules which came from the old update manager. The match rules are:
Perfect : [1.0.0, 1.0.0]
Equivalent : [1.0.0, 1.1.0)
Compatible : [1.0.0, 2.0.0)
Greater or Equal : [1.0.0]

CC said...

But why do I have to "include" the platform feature in my top level feature in order to have the configuration/org.eclipse.equinox.simpleconfigurator/bundles.info" generated?

Andrew Niefer said...

@CC (the previous comment was @Ian),
This is similar to the footnote [1] in the previous blog post, you are missing start level information.

Mostly for historical reason, PDE/Build is only automatically generating start levels for things that are included in the product. PDE/Build isn't following requires and so doesn't generate the start levels.

You need to add start level information to the adt.product file. There is some information in the help on what the default levels are. It looks like the product editor doesn't let you add levels for plug-ins that aren't included, so you would need to edit as xml and add:

<configurations>
<plugin id="org.eclipse.core.runtime" autoStart="true" startLevel="4" />
<plugin id="org.eclipse.equinox.simpleconfigurator" autoStart="true" startLevel="1" />
<plugin id="org.eclipse.equinox.common" autoStart="true" startLevel="2" />
<plugin id="org.eclipse.update.configurator" autoStart="true" startLevel="4" />
</configurations>


I also found two bugs, you will need to do the workaround from bug 283060

Ian Mayo said...

Hi,
I presume the closing braces for:
Equivalent : [1.0.0, 1.1.0)
Compatible : [1.0.0, 2.0.0)

were a typo, that they should be square?

CC said...

Andrew, I follow your previous post and create an empty "dropins" folder in the PDE headless build, but it seems like the "dropins" folder is not being scanned. I put a link file under it (that link file works for the old "links" folder) but I don't see the extra features/plugins showing up.

How to enable the "dropins" folder?

Andrew Niefer said...

@Ian, the ')' closing brace is correct. The equivalent and compatible match rules do not include the upper bound of the range.

@CC, for dropins, you will need to start org.eclipse.equinox.p2.reconciler.dropins (autoStart=true, startLevel=4) in the same way you started the other 4 bundles in my last comment.

Derek said...

Andrew, this is very helpful. I am trying to add my own feature into the build. My feature exists as a plugin feature project in the same workspace. I have added "com.xx.myfeature' into adt.project. When I build, I get:
BUILD FAILED
buildADT.xml:23: The following error occurred while executing this line:
productBuild.xml:36: The following error occurred while executing this line:
productBuild.xml:64: Unable to find feature: com.xx.myfeature.feature.

Any ideas on what I am doing wrong?

Andrew Niefer said...

Derek,
buildADT.xml defines "base" to be the directory containing the buidlADT.xml file. In adt.feature.build/builder/build.properties we define pluginPath=${base}. This is how the adt.feature.builder/features/adt.feature is found.

pluginPath is a list of extra places to look for features and plugins. The workspace does not get searched automatically, it needs to be listed.

So you could change pluginPath to be pluginPath=${base};${base}/..
or perhaps
pluginPath=${base};/path/to/com.xx.myfeature.feature

JamieV said...

Hi Andrew,

Can this setup be used with the standard Eclipse Export Product Wizard? It use to export fine before I made the changes you outlined in your blog. I now get "Cannot satisfy dependency" errors.

Thanks

Andrew Niefer said...

JamieV, This doesn't work when exporting from the UI because currently PDE/Build only follows feature inclusions, not requires. Build will not be generating metadata for the things required by the features in your product.

This means that the metadata needs to come from somewhere else, in the headless build this is done with context repositories. Export from the UI does not currently provide context repos (see bug 272061).

Also, it is the extra director calls that we add to the customAssembly.xml in part 1 that make the sub-components individually updateable. You won't be able to do that with an export from the UI.

Jan said...

Andrew, thanks a lot for your helpful explanations!

My product now supports updates of its components independently from each other :-)

However when launching my product form Eclipse it is not complete. The features from the context repositories are missing.

Is there a chance with your approach to launch my complete product from within Eclipse?

If not, what is your recommendation on how I can try out the plug-ins which I develop for my product?

Should I have a second product configuration with feature includes (and keep two product configurations in snyc)?

Andrew Niefer said...

@Jan, I haven't tried this but you can try editing your target Platform (Preferences -> Plug-in Development -> Target Platform -> Edit) to add the repositories (Add -> Software Site) and the features you are using to your target.

Jan said...

I have to add something to my last comment: After setting up the target I forgot to adjust my run configuration. Selecting my complete target in my run configuration leads to the desired result as far as I can see.

ddk said...

Hi Andrew,
it seems cvs link to example is not longer available, could you please share example in some other way.

Thank you,
Dmitry

Muller said...

Hi Andrew, thank you very much for this post.
I would like to enable updates for a similar project and thus I have two questions:
- Are your advice still relevant considering building a product with Eclipse 3.7 / 3.8 using PDE headlessly?
- Is there a way to retrieve the sample projects (such as the ADT project) you provided? (I was not able to retrieve them following links within these pages)

Andrew Niefer said...

I have made the examples available in git at http://git.eclipse.org/gitroot/pde/eclipse.pde.build.git under the examples folder.

Andrew Niefer said...

@Muller, I believe these blog posts are still relevant for recent releases of Eclipse. I haven't actually tried the examples recently so can't guarantee that they still work out of the box, but I am not aware of any significant changes that would invalidate them.