Maven Tycho

Aus SDQ-Wiki

General Remarks

This page is meant to collect pointers to Maven Tycho. Please note that projects such as Palladio or Vitruvius provide parent POMs that already integrate the best practices and tips below and provide sensible defaults for many open choices. Refer to the documentation of these projects to comply with their build standards.

If you are not contributing to one of these projects, you might still want to use the build instructions of MDSD.tools because they provide a good starting point for independent projects as well. Obviously, you have to care by yourself your the continuous integration system and execution of your build.

It is unlikely that this page will be up to date with the latest recommendations. Therefore, consider referring to publicly available and continuously maintained tutorials (see Pointers).

Pointers

Most Common Approach

In addition to your existing Eclipse extension, you have to provide the following items

  • Parent POM that defines commonly used Maven plugins
  • Aggregator POM that references all separate projects
  • Main POM in the project root that is called to build the complete extension
  • POM file for every project

The first three POM files can be merged into the main POM in the root folder for simple projects. If you create builds for an existing project like Palladio or Vitruvius, a parent POM usually already exists.

Parent POM

The parent POM defines commonly used plugins and properties. All other POMs reference it and reuse the definitions. The group ID and the version can be omitted in depending POMs.

In order to use tycho, you have to include the tycho-maven-plugin and the target-platform-configuration plugins into your build process. The former enables Tycho. The latter defines the target platform for the build process. In order to ensure properly working plugins on various platforms, you should add them to the configured environments. The dependencies are resolved by the P2 repositories given in the repositories section or by an Eclipse target platform file. The former is easier to use but the latter gives you more control regarding the used feature versions.

Additionally, it is beneficial to include the maven-compiler-plugin plugin and specify the targeted Java version. Thereby, build errors related to wrong Java versions can be detected easily.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>de.cooperateproject.plantumlpp</groupId>
  <artifactId>parent</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <properties>
    <tycho.version>0.24.0</tycho.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>

  <repositories>
    <repository>
      <id>eclipse</id>
      <layout>p2</layout>
      <url>http://download.eclipse.org/releases/mars</url>
    </repository>
  </repositories>

  <build>
    <plugins>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <source>${java.version}</source>
          <target>${java.version}</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.eclipse.tycho</groupId>
        <artifactId>tycho-maven-plugin</artifactId>
        <version>${tycho.version}</version>
        <extensions>true</extensions>
      </plugin>

      <plugin>
        <groupId>org.eclipse.tycho</groupId>
        <artifactId>target-platform-configuration</artifactId>
        <version>${tycho.version}</version>
        <configuration>    
          <environments>
            <environment>
              <os>linux</os>
              <ws>gtk</ws>
              <arch>x86</arch>
            </environment>
            <environment>
              <os>linux</os>
              <ws>gtk</ws>
              <arch>x86_64</arch>
            </environment>
            <environment>
              <os>win32</os>
              <ws>win32</ws>
              <arch>x86</arch>
            </environment>
            <environment>
              <os>win32</os>
              <ws>win32</ws>
              <arch>x86_64</arch>
            </environment>
            <environment>
              <os>macosx</os>
              <ws>cocoa</ws>
              <arch>x86_64</arch>
            </environment>
          </environments>
        </configuration>
      </plugin>
      
    </plugins>
  </build>

</project>

Aggregator POM

The aggregator POM references all other artifacts in the modules section except for the parent POM. The parent POM is referenced in the parent section instead. The aggregator is necessary to resolve dependencies to artifacts that are not available at a P2 repository because they are under development.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>de.cooperateproject.plantumlpp</groupId>
    <artifactId>parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <relativePath>../de.cooperateproject.plantumlpp.parent</relativePath>
  </parent>
  <artifactId>de.cooperateproject.plantumlpp.aggregator</artifactId>
  <packaging>pom</packaging>

  <modules>
    <module>../../features/de.cooperateproject.plantumlpp.feature</module>
    <module>../../bundles/de.cooperateproject.plantumlpp.notation2plant</module>
    <module>../../tests/de.cooperateproject.plantumlpp.notation2plant.tests</module>
    <module>../../bundles/de.cooperateproject.plantumlpp.notation2plant.generator</module>
    <module>../../tests/de.cooperateproject.plantumlpp.notation2plant.generator.tests</module>
    <module>../../bundles/edu.kit.ipd.sdq.commons.ecore2txt</module>
    <module>../../bundles/edu.kit.ipd.sdq.vitruvius.framework.util</module>
    <module>../../bundles/de.cooperateproject.plantumlpp.notation2plant.viewer</module>
  </modules>
</project>

Main POM

The main POM is located in the document root of the Eclipse extension and references the aggregator and the update site, as well as the parent. If this POM is called with a specific goal, all transitively referenced POMs are called with a specific goal. The build order is automatically derived by Maven.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <parent>
    <groupId>de.cooperateproject.plantumlpp</groupId>
    <artifactId>parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <relativePath>releng/de.cooperateproject.plantumlpp.parent</relativePath>
  </parent>
  <artifactId>de.cooperateproject.plantumlpp.main</artifactId>
  <packaging>pom</packaging>

  <modules>
    <module>releng/de.cooperateproject.plantumlpp.aggregator</module>
    <module>releng/de.cooperateproject.plantumlpp.updatesite</module>
  </modules>
</project>

Individual Artifact POM Files

The POM files for invidivual artifacts can be kept pretty simple. The only thing you need is the reference to the parent POM, the artifact id and the packaging type. In our context, the following packaging types are relevant:

  • eclipse-plugin
  • eclipse-test-plugin
  • eclipse-feature
  • eclipse-repository
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>de.cooperateproject.plantumlpp</groupId>
		<artifactId>parent</artifactId>
		<version>1.0.0-SNAPSHOT</version>
		<relativePath>../de.cooperateproject.plantumlpp.parent</relativePath>
	</parent>

	<artifactId>de.cooperateproject.plantumlpp.updatesite</artifactId>
	<packaging>eclipse-repository</packaging>

</project>

Please note that you can omit these individual POM files by telling tycho to create these files on demand. In order to do this, you have to create a .mvn folder in the root of your project with a file extensions.xml containing the following instructions (please use the same tycho version as in your POM files):

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

Special Tasks

Compiling Xtend Source Files

Xtend files can be compiled easily by adding the following snipped to your parent POM. The xtend files are translated to java files and compiled together with the remaining source files later. Please note that the dependency section has to match the xtex.version variable. The dependencies are only required because of a bug in the xtend-maven-plugin, which might be fixed in future versions.

<plugin>
	<groupId>org.eclipse.xtend</groupId>
	<artifactId>xtend-maven-plugin</artifactId>
	<version>${xtext.version}</version>
	<executions>
		<execution>
			<phase>generate-sources</phase>
			<goals>
				<goal>compile</goal>
			</goals>
			<configuration>
				<outputDirectory>xtend-gen</outputDirectory>
			</configuration>
		</execution>
	</executions>
	<dependencies>
		<dependency>
			<groupId>org.eclipse.jdt</groupId>
			<artifactId>org.eclipse.jdt.core</artifactId>
			<version>3.12.2</version>
		</dependency>
		<dependency>
			<groupId>org.eclipse.platform</groupId>
			<artifactId>org.eclipse.core.runtime</artifactId>
			<version>3.12.0</version>
		</dependency>
		<dependency>
			<groupId>org.eclipse.platform</groupId>
			<artifactId>org.eclipse.equinox.common</artifactId>
			<version>3.8.0</version>
		</dependency>
	</dependencies>
</plugin>

Deploying Source Files

To deploy the source files of plugins, it is necessary to use Maven plugins for creating source jars of the Eclipse plugins and the Eclipse features, as well as for handling source features by p2 updatesite generators. The general process is described here and the example code can be found on GitHub.

The tycho-source-plugin is necessary for automatically creating source-jars of the Eclipse plugins:

<plugin>
  <groupId>org.eclipse.tycho</groupId>
  <artifactId>tycho-source-plugin</artifactId>
  <version>${tycho.version}</version>
  <executions>
    <execution>
      <id>plugin-source</id>
      <goals>
        <goal>plugin-source</goal>
      </goals>
    </execution>
  </executions>
</plugin>

The tycho-source-features-plugin is necessary for automatically creating source-jars of the Eclipse features:

<plugin>
  <groupId>org.eclipse.tycho.extras</groupId>
  <artifactId>tycho-source-feature-plugin</artifactId>
  <version>${tycho.version}</version>
  <executions>
    <execution>
      <id>source-feature</id>
      <phase>package</phase>
      <goals>
        <goal>source-feature</goal>
      </goals>
    </execution>
  </executions>
</plugin>

The tycho-p2-plugin is necessary to correctly integreate sources into p2 updatesites:

<plugin>
  <groupId>org.eclipse.tycho</groupId>
  <artifactId>tycho-p2-plugin</artifactId>
  <version>${tycho.version}</version>
  <executions>
    <execution>
      <id>attached-p2-metadata</id>
      <phase>package</phase>
      <goals>
        <goal>p2-metadata</goal>
      </goals>
    </execution>
  </executions>
</plugin>

To integrate the sources-features into a p2 updatesite, they have to be referenced in the category.xml of the updatesite project. They must not be referenced with a url but by the original feature id with the suffix .source. For example, having a feature edu.kit.ipd.sdq.test.feature, the sources can be deployed on the updatesite by adding a feature with the id edu.kit.ipd.sdq.test.feature.source.

Local Building of Dependency Trees

Tycho can resolve dependencies via Maven or via Eclipse Update Sites. In Eclipse projects, dependencies are often only available via update sites. However, this makes testing a dependency tree quite complex: assume you have a project on which two other projects depend. If you locally change the first project, you can easily build it via Maven but the other two projects refer to the update site of the first project, which has not been updated yet. Therefore, you have to inject these new artifacts into your local build. The most obvious approach is to fire up a local webserver and replace the URLs of the update sites by hand. This works but does not scale for a whole dependency tree (i.e. projects that transitively depend on your changed project). In the following, we describe an approach that scales better:

For every project that yields new artifacts that have to be injected in the build process, do the following:

  • build the project locally using maven
  • navigate to the updatesite result directory (usually the folder target/repository
  • start a local webserver (see [1] for a list of one-line web servers) on a free port (e.g. 8080)
  • merge the following section into your maven settings file (~/.m2/settings.xml) and replace the example URLs of the PCM project with the matching values for your case
<settings>
  <mirrors>
    <mirror>
      <id>local-pcm-core</id>
      <name>Local PCM-Core Mirror</name>
      <url>http://localhost:8080/</url>
      <layout>p2</layout>
      <mirrorOf>https://updatesite.palladio-simulator.com/palladio-core-pcm/nightly/</mirrorOf>
      <mirrorOfLayouts>p2</mirrorOfLayouts>
    </mirror>
  </mirrors>
</settings>

The mirror setting intercepts the HTTP connection to the update site and redirects request to your local HTTP server. Please note that the mirror setting distinguishes HTTP and HTTPS connections. So, if you have HTTP and HTTPS connections to the same update site, you have to add two mirror settings for the respective URLs. Obviously, you have to build the projects in the appropriate order to make this approach work. For instance, you cannot expect to build a project that depends on a changed project before a mirror for the dependency exists.