Skip to content
nbauma109 edited this page Apr 28, 2024 · 15 revisions

Tycho Pomless Build Extension

Tycho is used to build Eclipse plug-ins, features, update sites, RCP applications and OSGi bundles with Maven. Maven itself requires some maven-related metadata like artifact/group id, versions, plugins to use, and packaging types. Most of that metadata is already available in the various files (MANIFEST.MF, feature.xml, product-file and so on) and actually Tycho requires this metadata to be synchronized to some extent, for example the pom.xml version must always match the MANIFEST.MF version. This leads to duplication of information and frustration of developers normally using the PDE-IDE for development as they must create "useless" pom.xml files and keep things in sync, builds fail late because inconsistencies are only detected when the actual bundle is built.

That's where the Tycho Pomless Build Extension can help to dramatically reduce the required configuration overhead, as all the boilerplate XML code could be generated automatically if you want to follow (and accept) some common patterns of deriving maven coordinates from OSGi-Artifacts.

Enabling pomless for your build

To enable pomless builds, create a folder named .mvn in the root of your build-tree and inside this folder a file named 'extensions.xml' with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<extensions>
  <extension>
    <groupId>org.eclipse.tycho</groupId>
    <artifactId>tycho-build</artifactId>
    <version>4.0.7</version>
  </extension>
</extensions>

You probably want to check if a newer version is available at https://oss.sonatype.org/. Make sure you have Sonatype repository configured:

<repositories>
  <repository>
    <id>sonatype.release</id>
    <name>Sonatype maven release repository</name>
    <url>https://oss.sonatype.org/content/repositories/releases/</url>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
  <repository>
    <id>sonatype.snapshot</id>
    <name>Sonatype maven snapshot repository</name>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    <snapshots>
      <updatePolicy>daily</updatePolicy>
    </snapshots>
  </repository>
</repositories>

Due to the nature of a build-extension you can't use properties from maven files, but System-properties if desired to specify the version actually used. From now on you can omit pom.xml files for the following cases.

general assumptions of tycho pomless

  • if there is a pom.xml in the folder, tycho pomless simply does nothing so you always have the choice to override tycho-pomless if needed
  • the group id is always inherited from the parent, this can't be overridden currently (see https://github.com/takari/polyglot-maven/issues/193)
  • the parent is always assumed to be in the default location (../pom.xml), you can override this (see section 'Advanced parent pom configurations')
  • even though you can choose the build structure as you like, it is recommended to follow the Tycho/pomless/Structured Build approach as you can then benefit from the simplest configuration

Define target platform configuration pomless

You can define your target as you like according to https://wiki.eclipse.org/Tycho/Target_Platform If you are using a target file, you can build that pomless if you follow these rules:

  • either there is only one target file in the folder
  • or the target to use is named like the folder

Tycho pomless will then generate the following maven coordinates for this: version: inherited from the parent artifactId: name of used target file without the .target extension name: name of the target

Structured Build: In a structured build you would locate the target under releng//.product

Special considerations: Placing target files into bundles/features is possible but will likely confuse tycho-pomless, it is recommended that you place the target into a plain project (Java/Maven/... is not required)

Building bundles/plugins pomless

If a folder contains a folder META-INF with a file MANIFEST.MF, tycho-pomless considers this as a plugin folder (see next section for the special case of test bundles) and will generate the following maven-coordinates for you:

  • version: version specified in manifest
  • artifactId: bundle-symbolic name specified in manifest
  • name: name of the bundle specified in manifest taking the default localization into account if given

Structured Build: In a structured build, you would locate bundles under bundles/

test-bundles

A special case are bundles named .test or .tests in the end or those with a special property in build.properties, as those are considered test bundles and executed as eclipse-tests. You can control this behavior with the following property in build.properties:

  • as from version 3.x: pom.model.packaging = eclipse-test-plugin/eclipse-plugin
  • before version 3.x: tycho.pomless.testbundle=true/false

to either force the detection as a test bundle or to deny it to be detected as a test bundle

Currently, it is not possible to configure this more, this is tracked in https://bugs.eclipse.org/bugs/show_bug.cgi?id=552370

Structured Build: In a structured build, you would locate bundles under tests/

Building features pomless

If a folder contains a feature.xml, tycho-pomless assumes this is a feature project and will generate the following maven-coordinates for you:

  • version: version specified in manifest
  • artifactId: id of feature
  • name: name of the feature taking the default localization into account if given

Building products/update-sites pomless

Products and Updatesite both use eclipse-repository packaging type and are thus handled together

Update-sites

If a folder contains a category.xml, tycho-pomless assumes this is an update-site project and will generate the following maven-coordinates for you:

  • version: inherited from parent
  • artifactId: .eclipse-repository
  • name: .eclipse-repository

Structured Build: In a structured build, you would locate updatesites under sites/

Products

If a folder contains a *.product file, tycho-pomless assumes this is a product project and will generate the following maven-coordinates for you:

  • version: version of product
  • artifactId: id of product
  • name: name of product

Structured Build: In a structured build, you would locate products under products/

Special considerations: Placing product/category.xml files into bundles/features is possible but will likely confuse tycho-pomless, it is recommended that you place the product into a plain project (Java/Maven/... is not required) and don't mix them. It is also possible to place many products into one directory and in that case, tycho will select an arbitrary one depending on your file-system.

pomless aggregation of modules

if you name a folder bundles, plugins, tests, features, sites, products or releng, and it contains sub-folders that are either pom-based or pomless modules, it assumes that this is an "aggregation" folder and will generate a pom file that lists all those as modules with the following maven-coordinates:

  • version: inherited from parent
  • groupid:
  • modules: all valid sub-folder-modules

Effectively, you now have toolset on your hands to build full PDE/Plugin artifact source with just one single pom.xml and we are even investigating ways how we even can omit that when using structured builds.

The root-pom then might look like this (of course, it also works if you only use bundles and features, for example):

 <project>
   .... list all your favorite maven config here like tycho versions and plugin configuration ...
  <modules>
   <module>releng/my-target-for-pomless</module>
   <module>bundles/</module>
   <module>features/</module>
   <module>tests/</module>
   <module>sites/</module>
   <module>products/</module>
  </module>
 </project>

Advanced parent pom configurations

You can, to some extent, configure how tycho tries to infer the parent:

  • define a system-property tycho.pomless.parent (defaults to "..") that configures the global default for searching parent poms (similar to tycho.localArtifacts this can't be configured in pom directly because of the early phase this is required)
  • you can define tycho.pomless.parent inside build.properties of individual bundle/fragment

If you are using the pomless aggregation of modules, you can reference the generated parent the following way:

 <parent>
  <groupId>...</groupId>
  <artifactId>...</artifactId>
  <version>...</version>
  <relativePath>../pom.tycho</relativePath>
 </parent>

FAQ

Why Tycho Pomless? Shouldn't it be just Tycho?

Even though they closely relate to each other, tycho-pomless is, contrary to Tycho, a build-extension that can be used independently of Tycho (you can even use different versions of tycho-pomless and tycho) and only generates the necessary metadata out of the RCP artifacts that is then used to actually do the build. Because of this, Tycho-pomless can't read configurations from maven poms (as these are not parsed at the time Tycho pomless kicks in), and only offers a subset of whole Tycho, but if you feel something is missing, feel free to open a bug here https://bugs.eclipse.org/bugs/enter_bug.cgi?product=Tycho

What are all those files starting with a dot I see during the build?

Tycho pomless uses the the polyglot-maven build extension that uses the name of the replacement-pom and generates a file named '.polyglot.'.

Each artifact (bundle, feature, product,/update-site, target) has its own handler and uses the real marker file (e.g. the MANIFEST.MF, feature.xml, .product/category.xml, ...) as a replacement pom, so you will see different files starting with .polyglot.*, with two exceptions:

  • polyglot requires replacement poms to be a regular (existing!) file, not a folder, thus .META-INF_MANIFEST.MF is generated and deleted after the build finishes, sadly if you kill the build via Eclipse these files are not cleaned up due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=38016
  • polyglot currently ignores all alternative files ending with .xml, (most notable feature.xml and category.xml), so also here a temporary file is created (see https://github.com/takari/polyglot-maven/issues/192 for details)
  • you might see another new file tycho.pom, that is generated when you use the automatic generation of module-aggregation files.

Useful Tips

  • You can output the generated poms with the following option: -Dpolyglot.dump.pom=pom.xml just keep in mind that pom.xml takes precedence over pomless configuration, so maybe choose a different name if you only like to use this for debug purpose!

Overwrite Group and Artifact IDs

The group id of generated poms is inherited from the parent pom, while the artifact id is derived from the directory, in which the polygot file is located. Within a reactor build, this id pair has to be unique.

You can influence this behavior by creating a build.properties in the same directory as the polygot file you want to modify, with the following entries:

pom.model.groupId=my.group.id
pom.model.artifactId=my.custom.artifact.id

There are even more properties supported, here is a full list:

pom.model.name = <custom name of the module>
pom.model.description = <custom description of the module>
pom.model.url = <project page of the module>
pom.model.packaging = <different packaging type> (not much useful here)
pom.model.version = <custom version of the module>
pom.model.groupId = <custom group id of the module>
pom.model.artifactId = <custom artifact id of the module>
pom.model.property.<custom property> = <custom value> ( see 'Define Properties' section below)

Use Case:

  • A project with multiple features or plugins directories.

Example:

project/
 +- component-A/
 |   +- plugins/
 |   |   + plugin1/
 |   |   + ...
 |   |   + build.properties     containing
 |   |                            pom.model.artifactId=component-a.features
 |   |                            tycho.pomless.parent=../../pom.xml
 |   |
 |   +- features/
 |       + feature1/
 |       + ...
 |       + build.properties     containing
 |                                pom.model.artifactId=component-A.features
 |                                tycho.pomless.parent=../../pom.xml
 |
 +- component-B/
 |   +- plugins/
 |   |   + ...
 |   |   + build.properties     containing
 |   |                            pom.model.artifactId=component-B.plugins
 |   |                            tycho.pomless.parent=../../pom.xml
 |   |
 |   +- features/
 |       + ...
 |       + build.properties     containing
 |                                pom.model.artifactId=component-B.features
 |                                tycho.pomless.parent=../../pom.xml
 |
 +- releng/
 +- products/
 +- pom.xml             parent.pom with module entries for 
                            <module>component-A/plugins</module>
                            <module>component-A/features</module>
                            <module>component-B/plugins</module>
                            <module>component-B/features</module>
                            <module>releng</module>
                            <module>products</module>
                            

Define Properties

You can define properties for a Maven-module by adding entries like pom.model.property.<custom-property-id> = <custom value> to the build.properties file in the same directory like the polyglot file. Each entry results in one property and as many (distinct) entries as desired can be added.

Example: The following entries in a build.properties file

pom.model.property.my-property = a-value
pom.model.property.another.flag = true

is equivalent to the following properties-section in the polyglot-pom within the same directory:

<properties>
  <my-property>a-value</my-property>
  <another.flag>true</another.flag>
</properties>

Declare Test-Plugins

By default, Tycho-pomless detects a Plug-in as 'Test Plug-in' if its Bundle-SymbolicName ends with ".test" or ".tests" and accordingly assigns it the packaging-type eclipse-test-plugin in the polyglot file.

In case your 'Test Plug-in' does not comply with that naming-convention (or a matching Plug-in is not meant to be a 'Test Plug-in'), you can enforce the project's packaging-type using a pom.model.packaging entry in the project's build.properties file:

To enforce a 'Test Plug-in' set

pom.model.packaging = eclipse-test-plugin

To enforce an ordinary Plug-in set

pom.model.packaging = eclipse-plugin

This is equivalent to a <packaging>eclipse-(test-)plugin</packaging> element in a pom.xml.

Specify Parent path

By default, Maven/Tycho-pomless assumes a project's parent in the parent directory. You can specify the relative path to the project's parent using a tycho.pomless.parent = <custom path to parent> entry in the build.properties file. The parent's groupId, artifactId and version (GAV) is read from the pom encountered at the specified location. As usual, the file name is assumed to be pom.xml if a directory is specified.

For example:

tycho.pomless.parent = ../releng/common-parent

is equivalent to a pom.xml with content

<parent>
	<groupId>foo.bar</groupId>
	<artifactId>parent</artifactId>
	<version>1.2.3-SNAPSHOT</version>
	<relativePath>../releng/common-parent</relativePath>
</parent>

Assuming the GAV in the pom at ../releng/common-parent/pom.xml is foo.bar:parent:1.2.3-SNAPSHOT.