Java Developer Guide/Using java-pkg-simple.eclass

From Gentoo Wiki
Jump to:navigation Jump to:search

java-pkg-simple.eclass is an eclass that provides a way to build Java packages on Gentoo in a simplistic manner. This is package system independent. Most packages can be built using java-pkg-simple.eclass global variables in the ebuild. Using such one can omit the entire src_prepare(), src_compile() and src_install() sections in most cases.

In case the package uses Maven as the build system, you can also use Gentoo tool app-portage/java-ebuilder to generate the ebuild skeleton. Though this application is still in experimental phase and some of its features are not yet supported by java-pkg-simple.eclass, it can give you fast overview of the package and also an ebuild skeleton to start with. You can also participate in improving the tool to make it more usable.

Basic Java ebuild skeleton

Users of vim get a basic skeleton automatically as shown below (provided by app-vim/gentoo-syntax):

user $mkdir -p repository/dev-java/foobar && cd $_
user $vim foobar-1.0.ebuild
# Copyright 2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

JAVA_PKG_IUSE="doc source test"
MAVEN_ID=""
MAVEN_PROVIDES=""
JAVA_TESTING_FRAMEWORKS="junit-4"

inherit java-pkg-2 java-pkg-simple

DESCRIPTION=""
HOMEPAGE=""
SRC_URI=""
S="${WORKDIR}/${P}"

LICENSE=""
SLOT="0"
KEYWORDS="~amd64"

CP_DEPEND=""

DEPEND="${CP_DEPEND}
	>=virtual/jdk-1.8:*"
RDEPEND="${CP_DEPEND}
	>=virtual/jre-1.8:*"

MAVEN_ID= in case of a single-jar ebuilds or MAVEN_PROVIDES= in case of a multi-jar ebuild are evaluated by java-ebuilder.

More detailed ebuild skeletons can be generated from packages providing pom.xml (Project Object Model) files by using the java-ebuilder.

Preparing sources

java-pkg-simple.eclass uses the normal src_unpack() and src_prepare() ebuild phase functions. Within src_prepare(), it is essential to call java-pkg-2_src_prepare and, until EAPI 8 in case there is a PATCHES array, also default.

CODE Patches are usually applied during src_prepare
PATCHES=(
	"${FILESDIR}"/${P}-foo.patch
	"${FILESDIR}"/${P}-bar.patch
)
 
src_prepare() {
    default # https://bugs.gentoo.org/780585
    java-pkg-2_src_prepare # for any actions (cp, rm, mv, sed or other) except patches
    ...
}
Note
Starting from EAPI 9 default will be called automatically and must not be added here.

Due to java-pkg-simple_src_install defining exactly what is getting installed in the src_install() phase, it is except some very rare cases not needed to remove bundled .jar or .class files. However, running java-pkg_clean can make packaging easier, not getting confused by stuff not created from the ebuild.

CODE java-pkg_clean with exceptions needed for tests
src_prepare() {
	java-pkg_clean ! -path "./shared/data/*" # keep icudata.jar, icutzdata.jar, testdata.jar
	java-pkg-2_src_prepare
}

Missing dependencies

If compilation doesn't succeed out of the box then usually one or more dependencies are missing. Grepping the build.log should then give a condensed summary:

user $grep 'does not exist' build.log | cut -d':' -f4-7 | sort | uniq
 package com.thoughtworks.xstream does not exist
 package com.thoughtworks.xstream.converters does not exist
 package com.thoughtworks.xstream.io does not exist
 package freemarker.template does not exist
 package org.nibblesec.tools does not exist


Typical examples using java-pkg-simple.eclass

CODE Using java-pkg-simple Global Variables
inherit java-pkg-2 java-pkg-simple

...

# One or more directories with sources in them relative to ${S}.
# It is mandatory.
JAVA_SRC_DIR="src/main/java"

# List of java packages to put on the classpath.
# It is mandatory in case the package has dependencies.
# No need to set this for dependencies listed in CP_DEPEND
JAVA_GENTOO_CLASSPATH="xalan:2,log4j:0"

# This is used to add raw jars to the classpath,
# jars either bundled or installed outside portage.
# It contains paths to jars, not package names.
# Paths can be absolute or relative to the package build system.
# Paths are colon separated.
JAVA_GENTOO_CLASSPATH_EXTRA="lib/bundled.jar:/path/to/system.jar"

# In case the package does not use UTF-8 encoding, you can specify
# the used encoding.
# It is used for javac and javadoc commands.
JAVA_ENCODING="ISO-8859-1"

# Optional additional arguments to be passed to javac.
JAVAC_ARGS="-Xms:64m"

# Optional additional arguments to be passed to javadoc.
JAVADOC_ARGS="-J-Xmx180m"

# This is used to add "Main-Class: " to MANIFEST.MF and also 
# triggers the creation of a launcher.  It can not be used in
# cases where the launcher requires optional arguments.
JAVA_MAIN_CLASS="com.biglybt.ui.Main"

One of the most common directory structures has src and resources directories like

CODE /var/tmp/portage/dev-java/commons-codec-1.15-r1/work/
work
└── commons-codec-1.15-src
    ├── pmd.xml
    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   └── org
        │   └── resources
        │       └── org
        └── test
            ├── java
            │   └── org
            └── resources
                └── org

This would accordingly need

CODE
JAVA_RESOURCE_DIRS="src/main/resources"
JAVA_SRC_DIR="src/main/java"

JAVA_TEST_RESOURCE_DIRS="src/test/resources"
JAVA_TEST_SRC_DIR="src/test/java"

resulting in an ebuild like

FILE commons-codec-1.15-r1.ebuildExample of a Gentoo Java ebuild
# Copyright 1999-2022 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

JAVA_PKG_IUSE="doc source test"
MAVEN_ID="commons-codec:commons-codec:1.15"
JAVA_TESTING_FRAMEWORKS="junit-4"

inherit java-pkg-2 java-pkg-simple

DESCRIPTION="Implementations of common encoders and decoders in Java"
HOMEPAGE="https://commons.apache.org/proper/commons-codec/"
SRC_URI="mirror://apache/commons/codec/source/${P}-src.tar.gz -> ${P}.tar.gz"
S="${WORKDIR}/${P}-src"

LICENSE="Apache-2.0"
SLOT="0"
KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~x86 ~amd64-linux ~x86-linux"

DEPEND="
	>=virtual/jdk-1.8:*
	test? (
		>=dev-java/commons-lang-3.11:3.6
	)
"

RDEPEND=">=virtual/jre-1.8:*"

JAVA_AUTOMATIC_MODULE_NAME="org.apache.commons.codec"
JAVA_RESOURCE_DIRS="src/main/resources"
JAVA_SRC_DIR="src/main/java"

JAVA_TEST_GENTOO_CLASSPATH="junit-4,commons-lang-3.6"
JAVA_TEST_RESOURCE_DIRS="src/test/resources"
JAVA_TEST_SRC_DIR="src/test/java"

Tests

Tests can run only when JAVA_PKG_IUSE has the test flag and JAVA_TESTING_FRAMEWORKS is filled.

Conditional test exclusions - JAVA_TEST_EXCLUDES

Tests can be excluded using the JAVA_TEST_EXCLUDES eclass variable. In cases where exclusions should apply only to certain Java versions it can be done using the ver_test function as shown in the following example. Disadvantage: Loosing tests if the excluded test class has more only one test.

CODE Excluding test classes for certain Java versions
src_test() {
	local vm_version="$(java-config -g PROVIDES_VERSION)"
	if ver_test "${vm_version}" -ge 17; then
		...
		JAVA_TEST_EXCLUDES+=(
			org.assertj.core.internal.classes.Classes_assertHasMethods_Test
			org.assertj.core.util.xml.XmlStringPrettyFormatter_prettyFormat_Test
		)
	fi
	java-pkg-simple_src_test
}

Conditional test exclusions - junit assume

A more sophisticated way to conditionally skip single tests is using junit assume as is demonstrated in commit #eabdf0892f

External tools

While in many if not most cases build.xml, pom.xml, build.gradle can be easily translated into ebuild it could get more chellenging when it comes to code generation be it java code, parsers or other code. There are already examples in the main ebuild repository of how it can be done solely in the ebuild without using external tools or even writing scripts for them.

Examples