Kura Addon Archetype
The Kura Addon Archetype is a Maven Archetype that allows to create a development environment with the following features:
- Maven-based build
- Template project for creating DEB packages
- Tycho-surefire based integration test template
- Uses a remote P2 repository for the target platform
The Kura Archetype JAR (kura-addon-archetype-<kura-version>.jar
) is available in the released artifacts and can be installed in the local maven repository with the following command:
mvn install:install-file \
-Dfile=./kura-addon-archetype-<kura-version>.jar \
-DgroupId=org.eclipse.kura \
-DartifactId=kura-addon-archetype \
-Dversion="<kura-version>" \
-Dpackaging=jar \
-DgeneratePom=true
Valid <kura-version>
values are 6.0.0-SNAPSHOT
and 6.0.0
. This archetype is available since Kura 6.0.0.
After that, it is possible to generate a project skeleton using the archetype with the following command:
mvn archetype:generate \
-DarchetypeArtifactId=kura-addon-archetype \
-DarchetypeGroupId=org.eclipse.kura \
-DarchetypeVersion="<kura-version>"
The command will start the generation of the archetype in interactive mode. Maven will ask for a few parameters on the command line:
- groupId : the Maven group id of the generated pom files, usually
org.eclipse.kura
- artifactId: the Maven artifact id of the generated parent pom file and the name of the generated top level project folder, usually something like
org.eclipse.kura.myartifact
- package: the Java package to be used for the main bundle, usually something like
org.eclipse.kura.myartifact
Other parameters like version and mainBundleVendor can be changed by answering n
after the Confirm properties configuration
prompt, which appears after editing the properties above.
A .gitignore
file is automatically added with a default configuration. The OSGI-INF
folder is omitted because it will be generated during tests at compile-time (this is necessary to make the PDE launcher work).
Add the generated sources to git
The project requires source control management via git
to correctly build. To add the project to git
run the following:
Once this steps are completed you can safely build the project.
Project structure
At the end of the procedure, the archetype will generate a subfolder in the working directory containing the following subfolders:
-
bundles: the directory where developed bundles can be placed. After the first archetype execution, this directory contains a single project, named as
artifactId.bundle
-
distrib: contains a project that builds a DEB package that installs the JAR produced in
bundles
in Kura's plugins folder/opt/eclipse/kura/plugins
. It is recommended to configure this project to customize the target package architecture and other parameters. The project code is commented with hints on the configurable options -
target-definition: The
.target
file contained in the project is the way to specify the project dependencies as maven artifacts, Tycho will then wrap them as bundles and make them available in the target platform. Since only released artifacts are published on Maven central, it is recommeded to perform a local Kura build to have the SNAPSHOT versions available -
tests: contains OSGi integration tests executed by the
tycho-surefire-plugin
Compile and run
The minimum supported Java version for compiling is Java 17. Compile the project with:
The build will produce the following system packages in distrib/target
:
- DEB installer (
<artifactId>_<version>_<debian-architecture>.deb
)
Installer properties like the architecture, organization name, package dependencies, and others can be configured in the distrib
project.
Depending on the system, the packages can be installed with:
After having installed the package, restart kura with:
During startup Kura will scan the plugins folder to pick up the installed JARs and include them in the framework's runtime.
It is possible to remove the installed plugins with:
Debug builds and Release builds
Since version 6.0.0 of the archetype, two type of builds are supported:
- Debug builds: active by default, generate artifacts whose version is computed from the timestamp and the
git
commit hash. Versioning scheme:X.X.X~git{timestamp}.{hash}-{revision}
- Release builds: generate release-ready artifacts. This build requires that no artifact/version is in "snapshot" mode. A "snapshot" version will result in a build failure. Versioning scheme:
X.X.X-{revision}
.
The build defaults to the debugBuild
profile, if the -DreleaseBuild
parameter is specified, the build selects the releaseBuild
profile.
By default the package.revision
is set to 1
. It can be overridden via CLI using the -Dpackage.revision=N
parameters.
Example:
IDE setup
We officially support two IDEs for developing Kura Addons: Eclipse IDE and Visual Studio Code. The following sections describe how to set up the projects in these IDEs.
Importing Projects in Visual Studio Code
Requirements
VSCode extensions: the following extensions will be automatically installed during the setup
- Eclipse PDE support for VS Code
- Language Support for Java by Red Hat
- Debugger for Java
- Java Test Runner
Kura metadata generator: this tool is used to generate the metadata required by VSCode to correctly load the Kura project. It is a Python tool that can be installed via pip
with the following command:
pip3 install https://github.com/eclipse-kura/metadata-generator/releases/download/<version>/metadata_generator-<version>-py3-none-any.whl
See latest release for updated installation instructions.
Instructions
1. Run the Kura metadata generator tool
After building the project with maven as described in the previous section, the next step is to generate the metadata required by VSCode to correctly load the Kura project.
Change the current working directory to the root of the add on archetype project (the one containing the pom.xml
file) and run the metadata generator tool with the following command:
2. Open VSCode
3. Follow the on-screen instructions
VS Code prompts the user to install the recommended extensions when a workspace is opened for the first time. The list of recommended extensions can be reviewed with the Extensions: Show Recommended Extensions
command.
After all the recommended extensions are installed, the project will start building
Finally, once the build completes, the workspace will be ready to use.
Importing Projects in Eclipse IDE
In Eclipse IDE , create a new workspace (it is not necessary to have the workspace in the root of the project) and import the projects with File | Import | Maven | Existing Maven Projects.
Note that if the workspace resides in the root of the project the parent POM file cannot be selected.
Load target platform
Open the .target file in the target-definition project and click on Set as Active Target Platform. Note that this will download the bundles from the Kura P2 repository and it may take a while to complete.
Eclipse IDE should rebuild the workspace automatically and show no errors. If errors appear, see next section.
(Optional) IDE errors resolution
In some cases it might be necessary to manually configure the build path. For the bundles and test projects, select Properties and then Project Natures and add the natures as in picture below.
Then, from the Java Build Path configure the correct source folder as in picture below.
Finally, configure the external Classpath dependencies by selecting the plugin dependencies from the Add Library.
On old Eclipse IDE installations it might be necessary to uninstall the Tycho configurator 0.1.0 plugin from Help | Install new software... | What is already installed?.
Architecture-specific development
The Addon Archetype standard procedure allows to build generic Debian installers not dependant on the architecture on which the bundle will be installed.
However, it is possible to customise the files in the distrib
folder to develop architecture-dependant installers: this might be necessary when a bundle contains native code (C/C++ libraries, jars that use JNI, etc.) or architecture-specific files (e.g. a systemd service file).
In the following sections we will see how this can be accomplished for the DEB packages. These steps assume that architecture-specific jars are built in the form of fragments of the architecture-agnostic java code. The architecture-specific jars will then be copied in the distrib
folder and included in the package.
Getting the source code
The first modification is the copy and rename of the source code target files generated under the bundles
project. Given the following bundles structure:
org.eclipse.kura.myartifact
├── bundles
│ ├── org.eclipse.kura.myartifact.bundle
│ ├── org.eclipse.kura.myartifact.bundle.aarch64
│ ├── org.eclipse.kura.myartifact.bundle.x86_64
....
org.eclipse.kura.myartifact.bundle
folder contains the agnostic code, while the org.eclipse.kura.myartifact.bundle.aarch64
and org.eclipse.kura.myartifact.bundle.x86_64
fragments contain the architecture-specific code. The distrib
folder will be modified to include the architecture-specific jars in the generated package.
First of all it is possible to define some properties in the distrib/pom.xml
file:
<addon.installation.dir>/opt/eclipse/kura/plugins/6s</addon.installation.dir>
<native.core.installation.dir>/opt/eclipse/kura/plugins/5</native.core.installation.dir>
...
<jar.name>org.eclipse.kura.myartifact.bundle</jar.name>
<jar.aarch64.core>org.eclipse.kura.myartifact.bundle.aarch64</jar.aarch64.core>
<jar.x86_64.core>org.eclipse.kura.myartifact.bundle.x86_64</jar.x86_64.core>
...
instead of
<deb.architecture>all</deb.architecture>
use the following
<deb.amd64.architecture>amd64</deb.amd64.architecture>
<deb.arm64.architecture>arm64</deb.arm64.architecture>
Tip
These properties are used to define the architecture-specific jars and the architecture-specific debian metadata. The addon.installation.dir
property is used to define the installation directory of the bundle in Kura. The native.core.installation.dir
property is used to define the installation directory of the native code in Kura. It is important that the fragments are installed in a higher level directory than the main bundle, otherwise Kura will not be able to load the native code.
The jar.name
property is used to define the name of the main bundle, while the jar.aarch64.core
and jar.x86_64.core
properties are used to define the names of the architecture-specific fragments.
Finally, the deb.amd64.architecture
and deb.arm64.architecture
properties are used to define the architecture-specific debian metadata.
The plugin responsible to copy and rename the jars is the copy-rename-maven-plugin
. The plugin is configured in the distrib/pom.xml
file as follows:
<execution>
<id>copy-and-rename-jar</id>
<phase>generate-sources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<sourceFile>${project.basedir}/../bundles/${jar.name}/target/${jar.name}-${project.version}.jar</sourceFile>
<destinationFile>target/${jar.name}_${project.version}.jar</destinationFile>
</configuration>
</execution>
To load also the architecture-specific jars, the plugin should be configured as follows:
<execution>
<id>copy-and-rename-source-jar</id>
<phase>generate-sources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<sourceFile>${project.basedir}/../bundles/${jar.name}/target/${jar.name}-${project.version}.jar</sourceFile>
<destinationFile>target/${jar.name}_${project.version}.jar</destinationFile>
</configuration>
</execution>
<execution>
<id>copy-and-rename-aarch64-architecture-jar</id>
<phase>generate-sources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<sourceFile>${project.basedir}/../bundles/${jar.aarch64.core}/target/${jar.aarch64.core}-${project.version}.jar</sourceFile>
<destinationFile>target/input_files/${jar.aarch64.core}_${project.version}.jar</destinationFile>
</configuration>
</execution>
<execution>
<id>copy-and-rename-x86_64-architecture-jar</id>
<phase>generate-sources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<sourceFile>${project.basedir}/../bundles/${jar.x86_64.core}/target/${jar.x86_64.core}-${project.version}.jar</sourceFile>
<destinationFile>target/input_files/${jar.x86_64.core}_${project.version}.jar</destinationFile>
</configuration>
</execution>
In this way, in the input_files
folder all the necessary jars will be copied and renamed to the correct name. The input_files
folder is used to store the files that will be included in the package.
Architecture dependant packages
The /distrib/deb/control/control
file contains the DEB package metadata. The standard file is configured as follows:
Package: [[package.name]]
Version: [[project.version]]
Section: admin
Priority: optional
Depends: kura
Architecture: [[deb.architecture]]
Maintainer: Eclipse Kura Developers <kura-dev@eclipse.org>
Description: [[summary]]
[[long.description]]
Homepage: https://eclipse-kura.github.io/kura/ (add correct link to documentation here)
The Architecture field is the one responsible to specify the architecture of the package. The value is set in the /distrib/pom.xml
file, by the property <deb.architecture>all</deb.architecture>
. The value all
means that the package can be installed on any architecture. This is the recommended value for packages that do not contain architecture-specific files.
To build a package that contains architecture-specific files, it is necessary to separate the control files of the different architectures (namely, aarch64
and amd64
). To do so, create two directories in the distrib/deb/
folder with this structure:
control
file must be created in the distrib/deb/<arch>/
folder. These folders could contain also the postinst
and postrm
files, used to execute commands after the installation and before the removal of the package. The content of these files is not relevant for this example, but they can be used to execute commands that are necessary for the correct installation of the package.
An example of control
file for the arm64
architecture is:
Package: [[package.name]]
Version: [[project.version]]
Section: admin
Priority: optional
Depends: kura
Architecture: [[deb.arm64.architecture]]
Maintainer: Eclipse Kura Developers <kura-dev@eclipse.org>
Description: [[summary]]
[[long.description]]
Homepage: https://eclipse-kura.github.io/kura/ (add correct link to documentation here)
The same file for the amd64
architecture will just change the Architecture
field to [[deb.amd64.architecture]]
.
Finally, the plugin responsible of generating the DEB package is the jdeb
plugin. The default execution is configured in the distrib/pom.xml
file as follows:
<plugin>
<groupId>org.vafer</groupId>
<artifactId>jdeb</artifactId>
<version>1.12</version>
<executions>
<execution>
<id>generate-deb</id>
<phase>package</phase>
<goals>
<goal>jdeb</goal>
</goals>
<configuration>
<verbose>true</verbose>
<deb>${basedir}/target/${package.name}_${project.version}_${deb.architecture}.deb</deb>
<controlDir>${project.basedir}/deb/control</controlDir>
<skipPOMs>false</skipPOMs>
<dataSet>
<data>
<src>${basedir}/target/${jar.name}_${project.version}.jar</src>
<dst>${jar.name}_${project.version}.jar</dst>
<type>file</type>
<mapper>
<type>perm</type>
<prefix>${addon.installation.dir}</prefix>
<user>kurad</user>
<group>kurad</group>
<filemode>600</filemode>
</mapper>
</data>
</dataSet>
</configuration>
</execution>
</executions>
</plugin>
To build the architecture-dependant installers, the execution must change to:
<execution>
<id>generate-arm64-deb</id>
<phase>package</phase>
<goals>
<goal>jdeb</goal>
</goals>
<configuration>
<verbose>true</verbose>
<deb>${basedir}/target/deb/${output.installer.name}_${project.version}_${deb.arm64.architecture}.deb</deb>
<controlDir>${project.basedir}/deb/arm64</controlDir>
<skipPOMs>false</skipPOMs>
<dataSet>
<data>
<src>${basedir}/target/input_files/${jar.name}_${project.version}.jar</src>
<dst>${jar.name}_${project.version}.jar</dst>
<type>file</type>
<mapper>
<type>perm</type>
<prefix>${addon.installation.dir}</prefix>
<user>kurad</user>
<group>kurad</group>
<filemode>600</filemode>
</mapper>
</data>
<data>
<src>${basedir}/target/input_files/${jar.aarch64.core}_${project.version}.jar</src>
<dst>${jar.aarch64.core}_${project.version}.jar</dst>
<type>file</type>
<mapper>
<type>perm</type>
<prefix>${native.core.installation.dir}</prefix>
<user>kurad</user>
<group>kurad</group>
<filemode>600</filemode>
</mapper>
</data>
</dataSet>
</configuration>
</execution>
A similar execution can be used for the amd64
architecture, just changing the deb
and controlDir
fields to point to the correct architecture (and change the execution id
if they're present at the same time). Also in the src
and dst
fields must be changed to point to the correct architecture-specific jars.
The final result will consist of two DEB packages, one for each architecture. They will be found in the distrib/target/deb/
folder with the following names: