Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement Jlink plugin #951

Merged
merged 53 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
c12302c
feat: add jlink plugin
vpa1977 Jan 6, 2025
cf7a732
doc: add jlink plugin documentation
vpa1977 Jan 6, 2025
e08828c
doc: amend wordlist to include jlink
vpa1977 Jan 6, 2025
ef11438
doc: include jlink plugin in toc
vpa1977 Jan 7, 2025
555b95b
doc: update wordlist for jlink plugin
vpa1977 Jan 7, 2025
9f87a57
chore: install openjdk-21-jdk for jlink test
vpa1977 Jan 7, 2025
80976e8
doc: add changelog rst
vpa1977 Jan 7, 2025
c629c91
test(jlink): add test for different java version
vpa1977 Jan 7, 2025
52e1075
lint: update formatting
vpa1977 Jan 7, 2025
d447abe
fix: include all jar files in the classpath
vpa1977 Jan 8, 2025
30afbc8
test: add unit tests
vpa1977 Jan 8, 2025
f5d65a4
Merge branch 'main' into jlink-plugin
vpa1977 Jan 8, 2025
44db443
feat: use JAVA_HOME and deduce version from it
vpa1977 Jan 20, 2025
8af0327
doc: update documentation
vpa1977 Jan 20, 2025
a59bfb0
Merge branch 'jlink-plugin' of github.com:vpa1977/craft-parts into jl…
vpa1977 Jan 20, 2025
14ca2d3
Merge remote-tracking branch 'upstream/main' into jlink-plugin
vpa1977 Jan 20, 2025
bc74bd6
lint: dependant -> dependent
vpa1977 Jan 20, 2025
2452b20
test: drop test for java version
vpa1977 Jan 20, 2025
213d18f
doc: add missing words for the spellcheck
vpa1977 Jan 20, 2025
5922bbb
test: drop integration test for java_version property
vpa1977 Jan 20, 2025
6251ec3
lint: drop unused import
vpa1977 Jan 20, 2025
3bb327b
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 23, 2025
b34381b
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 23, 2025
04224b6
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 23, 2025
1a7bda3
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 23, 2025
475b098
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 23, 2025
f3a0c7f
Update docs/reference/changelog.rst
vpa1977 Jan 23, 2025
41ecc03
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 23, 2025
693a1fe
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 23, 2025
0996063
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 23, 2025
a8d6168
Merge remote-tracking branch 'upstream/main' into jlink-plugin
vpa1977 Jan 23, 2025
126ee3d
fix: set and validate JAVA_HOME
vpa1977 Jan 23, 2025
789693c
doc: format yaml blocks
vpa1977 Jan 23, 2025
972b828
doc: rename jar -> JAR
vpa1977 Jan 23, 2025
62b2dcd
doc: openjdk -> OpenJDK
vpa1977 Jan 23, 2025
05625d3
doc: declare openjdk build-package
vpa1977 Jan 23, 2025
fdea496
Merge branch 'main' into jlink-plugin
vpa1977 Jan 23, 2025
c08ba2d
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 24, 2025
52cc3e0
Update craft_parts/plugins/jlink_plugin.py
vpa1977 Jan 24, 2025
318bf6b
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 24, 2025
68c754d
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 24, 2025
4fcb352
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 24, 2025
61e3ac2
Update tests/unit/plugins/test_jlink_plugin.py
vpa1977 Jan 24, 2025
0bf53a5
Update docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 Jan 24, 2025
4935f90
doc: specify how to install openjdk for jlink plugin
vpa1977 Jan 25, 2025
b19af95
doc: fix typo in jlink link
vpa1977 Jan 25, 2025
e472123
Merge branch 'main' into jlink-plugin
vpa1977 Jan 25, 2025
07aaeb0
doc: update changelog
vpa1977 Jan 25, 2025
99d8bf9
fix: add explicitly use jlink options
vpa1977 Jan 29, 2025
b65efb6
doc: exclude jvm from staging
vpa1977 Jan 29, 2025
7647c59
Merge branch 'jlink-plugin' of github.com:vpa1977/craft-parts into jl…
vpa1977 Jan 29, 2025
fb203be
Merge branch 'main' into jlink-plugin
vpa1977 Jan 29, 2025
7a38f56
style: black
mr-cal Jan 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ jobs:
fi
echo "::endgroup::"
echo "::group::JDK"
sudo apt-get install -y openjdk-17-jdk-headless openjdk-21-jdk-headless openjdk-8-jdk-headless
sudo apt-get install -y openjdk-17-jdk openjdk-21-jdk openjdk-8-jdk-headless
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
echo "::endgroup::"
- name: Install uv
uses: astral-sh/setup-uv@v4
Expand Down
143 changes: 143 additions & 0 deletions craft_parts/plugins/jlink_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2024 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""The JLink plugin."""

from typing import Literal, cast

from overrides import override

from .base import Plugin
from .properties import PluginProperties
from .validator import PluginEnvironmentValidator


class JLinkPluginProperties(PluginProperties, frozen=True):
"""The part properties used by the JLink plugin."""

plugin: Literal["jlink"] = "jlink"
jlink_jars: list[str] = []


class JLinkPluginEnvironmentValidator(PluginEnvironmentValidator):
"""Check the execution environment for the JLink plugin.

:param part_name: The part whose build environment is being validated.
:param env: A string containing the build step environment setup.
"""

@override
def validate_environment(
self, *, part_dependencies: list[str] | None = None
) -> None:
"""Ensure the environment contains dependencies needed by the plugin.

:param part_dependencies: A list of the parts this part depends on.

:raises PluginEnvironmentValidationError: If go is invalid
and there are no parts named go.
"""
self.validate_dependency(
dependency="jlink", plugin_name="jlink", part_dependencies=part_dependencies
)


class JLinkPlugin(Plugin):
"""Create a Java Runtime using JLink."""

properties_class = JLinkPluginProperties
validator_class = JLinkPluginEnvironmentValidator

@override
def get_build_packages(self) -> set[str]:
"""Return a set of required packages to install in the build environment."""
return set()

@override
def get_build_environment(self) -> dict[str, str]:
"""Return a dictionary with the environment to use in the build step."""
return {}

@override
def get_build_snaps(self) -> set[str]:
"""Return a set of required snaps to install in the build environment."""
return set()

@override
def get_build_commands(self) -> list[str]:
"""Return a list of commands to run during the build step."""
options = cast(JLinkPluginProperties, self._options)

commands = []

# ensure that JAVA_HOME/bin is the first entry on the path
# this allows to select JDK installation
commands.append("PATH=${JAVA_HOME:-$(which jlink)}/bin:$PATH")
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved

# extract jlink version and use it to define the destination
# and multi-release jar version for the dependency enumeration
commands.append("JLINK_VERSION=$(jlink --version)")
commands.append(
"DEST=usr/lib/jvm/java-${JLINK_VERSION%%.*}-openjdk-${CRAFT_TARGET_ARCH}"
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
)
commands.append("MULTI_RELEASE=${JLINK_VERSION%%.*}")

# find application jars - either all jars in the staging area
# or a list specified in jlink_jars option
if len(options.jlink_jars) > 0:
jars = " ".join(["${CRAFT_STAGE}/" + x for x in options.jlink_jars])
commands.append(f"PROCESS_JARS={jars}")
else:
commands.append("PROCESS_JARS=$(find ${CRAFT_STAGE} -type f -name *.jar)")

# create temp folder
commands.append("mkdir -p ${CRAFT_PART_BUILD}/tmp")
# extract jar files into temp folder - spring boot fat jar
# contains dependent jars inside
commands.append(
"(cd ${CRAFT_PART_BUILD}/tmp && for jar in ${PROCESS_JARS}; do jar xvf ${jar}; done;)"
)
# create classpath - add all dependent jars and all staged jars
commands.append("CPATH=.")
commands.append(
"""
find ${CRAFT_PART_BUILD}/tmp -type f -name *.jar | while IFS= read -r file; do
CPATH=$CPATH:${file}
done
find ${CRAFT_STAGE} -type f -name *.jar | while IFS= read -r file; do
CPATH=$CPATH:${file}
done
"""
)
commands.append(
"""if [ "x${PROCESS_JARS}" != "x" ]; then
deps=$(jdeps --class-path=${CPATH} -q --recursive --ignore-missing-deps \
--print-module-deps --multi-release ${MULTI_RELEASE} ${PROCESS_JARS})
else
deps=java.base
fi
"""
)
commands.append("INSTALL_ROOT=${CRAFT_PART_INSTALL}/${DEST}")

commands.append(
"rm -rf ${INSTALL_ROOT} && jlink --add-modules ${deps} --output ${INSTALL_ROOT}"
)
# create /usr/bin/java link
commands.append(
"(cd ${CRAFT_PART_INSTALL} && mkdir -p usr/bin && ln -s --relative ${DEST}/bin/java usr/bin/)"
)
return commands
2 changes: 2 additions & 0 deletions craft_parts/plugins/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from .dump_plugin import DumpPlugin
from .go_plugin import GoPlugin
from .go_use_plugin import GoUsePlugin
from .jlink_plugin import JLinkPlugin
from .make_plugin import MakePlugin
from .maven_plugin import MavenPlugin
from .meson_plugin import MesonPlugin
Expand Down Expand Up @@ -57,6 +58,7 @@
"dump": DumpPlugin,
"go": GoPlugin,
"go-use": GoUsePlugin,
"jlink": JLinkPlugin,
"make": MakePlugin,
"maven": MavenPlugin,
"meson": MesonPlugin,
Expand Down
9 changes: 9 additions & 0 deletions docs/common/craft-parts/craft-parts.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ InvalidSourceOptions
InvalidSourceType
Iterable
JavaPlugin
JLink
JLinkPlugin
JLinkPluginEnvironmentValidator
JLinkPluginProperties
JSON
LDFLAGS
LLVM
Expand Down Expand Up @@ -145,6 +149,7 @@ NpmPlugin
NpmPluginEnvironmentValidator
NpmPluginProperties
OCI
OpenJDK
OSError
OsRelease
OsReleaseCodenameError
Expand Down Expand Up @@ -313,6 +318,7 @@ chmod
chroot
chrooted
classmethod
classpath
classvar
cli
cls
Expand Down Expand Up @@ -368,7 +374,9 @@ ing
initialized
iterable
iojs
jdeps
jdk
jlink
jre
js
json
Expand Down Expand Up @@ -397,6 +405,7 @@ oci
ok
onboarding
opencontainers
openjdk
organization
organize
organized
Expand Down
99 changes: 99 additions & 0 deletions docs/common/craft-parts/reference/plugins/jlink_plugin.rst
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
.. _craft_parts_jlink_plugin:

JLink plugin
medubelko marked this conversation as resolved.
Show resolved Hide resolved
=============

The JLink plugin can be used for Java projects where you would want to
deploy Java runtime specific for your application or install a minimal
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
Java runtime.


Keywords
--------

This plugin uses the common :ref:`plugin <part-properties-plugin>` keywords as
well as those for :ref:`sources <part-properties-sources>`.

Additionally, this plugin provides the plugin-specific keywords defined in the
following sections.

jlink-jars
~~~~~~~~~~~~~~~~~~
**Type:** list of strings

List of paths to jar files of your application. If not specified, plugin
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
will find all jar files in the staging area.

Dependencies
------------

The plugin expects OpenJDK to be available on the system and contain
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
``jlink`` executable, unless a part named ``jlink-deps`` is defined.
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
In this case, the plugin will assume that this part will stage the
openjdk to be used in the build step.
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved

If the system has multiple OpenJDK installations available, it
should be selected by setting the ``JAVA_HOME`` environment variable.
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: yaml

parts:
runtime:
plugin: jlink
build-packages:
- openjdk-21-jdk
build-environment:
- JAVA_HOME: /usr/jvm/java-21-openjdk-${CRAFT_ARCH_BUILD_FOR}
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved


The user is expected to stage openjdk dependencies either by installing
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
an appropriate openjdk slice:
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: yaml

parts:
runtime:
plugin: jlink
after:
- deps

deps:
plugin: nil
stage-packages:
- openjdk-21-jre-headless_security

or by installing the dependencies directly:
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: yaml

parts:
runtime:
plugin: jlink
after:
- deps

deps:
plugin: nil
stage-packages:
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
- libc6_libs
- libgcc-s1_libs
- libstdc++6_libs
- zlib1g_libs
- libnss3_libs


How it works
------------

During the build step, the plugin performs the following actions:

* Finds all jar files in the staging area or selects jars specified in
``jlink_jars``.
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
* Unpacks jar files to the temporary location and concatenates all embedded jars
into `jdeps <jdeps_>`_ classpath.
* Runs `jdeps <jdeps_>`_ to discover Java modules required for the staged jars.
* Runs `jlink <jlink_>`_ to create a runtime image from the build JDK.


.. _`jdeps`: https://docs.oracle.com/en/java/javase/21/docs/specs/man/jdeps.html
.. _`jlink`: https://docs.oracle.com/en/java/javase/21/docs/specs/man/jlink.html
30 changes: 30 additions & 0 deletions docs/reference/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Changelog
the ctl server and output stream processing selector loops.
- Get the error output from step scriptlet execution and surface it when
raising ScriptletRunError.
- Add :ref:`jlink plugin<craft_parts_jlink_plugin>` for setting up Java
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
runtime.

2.2.2 (2025-MM-DD)
------------------
Expand All @@ -22,6 +24,34 @@ Documentation:

- Correct the Maven plugin docstring to refer to Maven from Go.

2.3.0 (unreleased)
vpa1977 marked this conversation as resolved.
Show resolved Hide resolved
------------------

- Change craftctl communication mechanism to unix sockets to consolidate
the ctl server and output stream processing selector loops.
- Get the error output from step scriptlet execution and surface it when
raising ScriptletRunError.

2.2.2 (2025-MM-DD)
------------------

Bug fixes:

- Make sure the :ref:`uv plugin<craft_parts_uv_plugin>` is re-entrant on
source changes.

Documentation:

- Correct the Maven plugin docstring to refer to Maven from Go.

2.3.0 (2025-XX-XX)
------------------

New features:

- Add :ref:`jlink plugin<craft_parts_jlink_plugin>` for setting up Java
runtime.

2.2.1 (2024-12-19)
------------------

Expand Down
1 change: 1 addition & 0 deletions docs/reference/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ lifecycle.
/common/craft-parts/reference/plugins/dump_plugin.rst
/common/craft-parts/reference/plugins/go_plugin.rst
/common/craft-parts/reference/plugins/go_use_plugin.rst
/common/craft-parts/reference/plugins/jlink_plugin.rst
/common/craft-parts/reference/plugins/make_plugin.rst
/common/craft-parts/reference/plugins/maven_plugin.rst
/common/craft-parts/reference/plugins/meson_plugin.rst
Expand Down
Loading
Loading