diff --git a/rockcraft/plugins/maven_plugin.py b/rockcraft/plugins/maven_plugin.py new file mode 100644 index 000000000..3f295f97d --- /dev/null +++ b/rockcraft/plugins/maven_plugin.py @@ -0,0 +1,76 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright 2023 Canonical Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""The Rockcraft Maven plugin.""" +import logging +from textwrap import dedent + +from craft_parts.plugins import maven_plugin +from overrides import override # type: ignore[reportUnknownVariableType] + +logger = logging.getLogger(__name__) + +# Template for the sitecustomize module that we'll add to the payload so that +# the pip-installed packages are found regardless of how the interpreter is +# called. +SITECUSTOMIZE_TEMPLATE = dedent( + """ + # sitecustomize added by Rockcraft. + import site + import sys + + major, minor = sys.version_info.major, sys.version_info.minor + site_dir = f"/lib/python{major}.{minor}/site-packages" + dist_dir = "/usr/lib/python3/dist-packages" + + # Add the directory that contains the venv-installed packages. + site.addsitedir(site_dir) + + if dist_dir in sys.path: + # Make sure that this site-packages dir comes *before* the base-provided + # dist-packages dir in sys.path. + path = sys.path + site_index = path.index(site_dir) + dist_index = path.index(dist_dir) + + if dist_index < site_index: + path[dist_index], path[site_index] = path[site_index], path[dist_index] + + EOF + """ +).strip() + + +class MavenPlugin(maven_plugin.MavenPlugin): + """A MavenPlugin plugin for Rockcraft. + + This plugin extends Craft-parts' vanilla Maven plugin to properly + use and install the Java VM. Specifically: + + - Do not link java executable to /bin/java + - Do not include staging area in the PATH + """ + + @override + def _get_java_link_commands(self) -> list[str]: + """Get the bash commands to provide /bin/java symlink.""" + return [] + + @override + def get_build_environment(self) -> dict[str, str]: + env = super().get_build_environment() + env["PATH"] = "/usr/bin" + return env diff --git a/rockcraft/plugins/register.py b/rockcraft/plugins/register.py index 5434e4cbc..f4387de69 100644 --- a/rockcraft/plugins/register.py +++ b/rockcraft/plugins/register.py @@ -19,6 +19,7 @@ import craft_parts from craft_parts.plugins.plugins import PluginType +from .maven_plugin import MavenPlugin from .poetry_plugin import PoetryPlugin from .python_plugin import PythonPlugin @@ -30,4 +31,4 @@ def register() -> None: def get_plugins() -> dict[str, PluginType]: """Get a dict of Rockcraft-specific plugins.""" - return {"poetry": PoetryPlugin, "python": PythonPlugin} + return {"poetry": PoetryPlugin, "python": PythonPlugin, "maven": MavenPlugin} diff --git a/tests/spread/rockcraft/plugin-maven/rockcraft.yaml b/tests/spread/rockcraft/plugin-maven/rockcraft.yaml new file mode 100644 index 000000000..6dc6833af --- /dev/null +++ b/tests/spread/rockcraft/plugin-maven/rockcraft.yaml @@ -0,0 +1,35 @@ +name: bare-build-2404 +base: bare +build-base: ubuntu@24.04 + +version: '0.1' +summary: A rock that bundles a Maven project. +description: A rock that bundles a Python project. +license: GPL-3.0 +platforms: + amd64: + +services: + test: + command: /usr/lib/jvm/java-21-openjdk-${CRAFT_ARCH_BUILD_FOR}/bin/java -jar /jar/sample-0.0.1-SNAPSHOT.jar + override: replace + startup: enabled + +parts: + maven-sample: + plugin: maven + source: sample + stage-packages: + - openjdk-21-jre-headless_core + - base-files_base + build-packages: + - maven + - openjdk-21-jdk-headless + # replace chiselled image with jlink + override-stage: | + craftctl default + rm -rf ${CRAFT_STAGE}/usr/lib/jvm/java-21-openjdk-${CRAFT_ARCH_BUILD_FOR} + jlink --no-header-files --no-man-pages --strip-debug \ + --add-modules java.base,java.xml,java.logging,jdk.net \ + --output ${CRAFT_STAGE}/usr/lib/jvm/java-21-openjdk-${CRAFT_ARCH_BUILD_FOR} + touch ${CRAFT_STAGE}/usr/lib/jvm/java-21-openjdk-${CRAFT_ARCH_BUILD_FOR}/lib/jvm.cfg-default diff --git a/tests/spread/rockcraft/plugin-maven/sample/pom.xml b/tests/spread/rockcraft/plugin-maven/sample/pom.xml new file mode 100644 index 000000000..9c8a762b6 --- /dev/null +++ b/tests/spread/rockcraft/plugin-maven/sample/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + test + sample + 0.0.1-SNAPSHOT + sample + + 8 + 8 + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + + test.Test + + + + + + + diff --git a/tests/spread/rockcraft/plugin-maven/sample/src/main/java/test/Test.java b/tests/spread/rockcraft/plugin-maven/sample/src/main/java/test/Test.java new file mode 100644 index 000000000..7871063ae --- /dev/null +++ b/tests/spread/rockcraft/plugin-maven/sample/src/main/java/test/Test.java @@ -0,0 +1,7 @@ +package test; + +public class Test { + public static void main(String[] args) { + System.out.println("hello world"); + } +} diff --git a/tests/spread/rockcraft/plugin-maven/task.yaml b/tests/spread/rockcraft/plugin-maven/task.yaml new file mode 100644 index 000000000..7776a9e12 --- /dev/null +++ b/tests/spread/rockcraft/plugin-maven/task.yaml @@ -0,0 +1,21 @@ +summary: Maven plugin tests +execute: | + SCENARIO="plugin-maven" + ROCK_FILE="${SCENARIO}_0.1_amd64.rock" + IMAGE="${SCENARIO}:0.1" + + # Build the rock & load it into docker + run_rockcraft pack + test -f ${ROCK_FILE} + rockcraft.skopeo copy oci-archive:${ROCK_FILE} docker-daemon:${IMAGE} + docker images + rm ${ROCK_FILE} + + # Run the packaged project, both via the console script and via "python -m" + docker run --rm $IMAGE exec hello | MATCH "hello world" + + docker system prune -a -f + + # Rebuild the java project + touch sample/src/main/java/test/Test.java + rockcraft pack