General Gradle work - toolchains

This commit is contained in:
Steve Ebersole 2023-08-07 20:05:47 -05:00 committed by Christian Beikov
parent 1374a2b518
commit 1589d1efe3
13 changed files with 644 additions and 141 deletions

View File

@ -26,6 +26,7 @@ plugins {
id 'biz.aQute.bnd' version '6.3.1' apply false id 'biz.aQute.bnd' version '6.3.1' apply false
id 'org.checkerframework' version '0.6.25' id 'org.checkerframework' version '0.6.25'
id 'org.hibernate.orm.build.jdks'
id 'io.github.gradle-nexus.publish-plugin' version '1.1.0' id 'io.github.gradle-nexus.publish-plugin' version '1.1.0'
@ -46,9 +47,7 @@ task release {
"themselves if they have any release-related activities to perform" "themselves if they have any release-related activities to perform"
doFirst { doFirst {
def javaVersionsInUse = [gradle.ext.javaVersions.main.compiler, gradle.ext.javaVersions.main.release, def javaVersionsInUse = jdkVersions.allVersions
gradle.ext.javaVersions.test.compiler, gradle.ext.javaVersions.test.release,
gradle.ext.javaVersions.test.launcher].toSet()
if ( javaVersionsInUse != [JavaLanguageVersion.of( 11 )].toSet() ) { if ( javaVersionsInUse != [JavaLanguageVersion.of( 11 )].toSet() ) {
throw new IllegalStateException( "Please use JDK 11 to perform the release. Currently using: ${javaVersionsInUse}" ) throw new IllegalStateException( "Please use JDK 11 to perform the release. Currently using: ${javaVersionsInUse}" )
} }

View File

@ -25,11 +25,10 @@ apply from: rootProject.file( 'gradle/module.gradle' )
apply from: rootProject.file( 'gradle/libraries.gradle' ) apply from: rootProject.file( 'gradle/libraries.gradle' )
apply from: rootProject.file( 'gradle/databases.gradle' ) apply from: rootProject.file( 'gradle/databases.gradle' )
apply plugin: 'org.hibernate.orm.database-service'
apply plugin: 'java-library' apply plugin: 'java-library'
apply plugin: 'biz.aQute.bnd.builder' apply plugin: 'biz.aQute.bnd.builder'
apply plugin: 'org.hibernate.orm.database-service' apply plugin: 'org.hibernate.orm.database-service'
apply plugin: 'org.hibernate.orm.build.java-module'
apply plugin: 'org.checkerframework' apply plugin: 'org.checkerframework'
@ -159,58 +158,6 @@ tasks.withType( JavaCompile ) {
// ] // ]
} }
if ( !gradle.ext.javaToolchainEnabled ) {
tasks.compileJava.configure {
sourceCompatibility = JavaVersion.toVersion( gradle.ext.javaVersions.main.release )
targetCompatibility = JavaVersion.toVersion( gradle.ext.javaVersions.main.release )
}
tasks.compileTestJava.configure {
sourceCompatibility = JavaVersion.toVersion( gradle.ext.javaVersions.test.release )
targetCompatibility = JavaVersion.toVersion( gradle.ext.javaVersions.test.release )
}
}
else {
// Configure generated bytecode
// "sourceCompatibility" is not supported with toolchains. We have to work around that limitation.
tasks.compileJava.configure {
options.release = gradle.ext.javaVersions.main.release.asInt()
// Needs add-opens because of https://github.com/gradle/gradle/issues/15538
options.forkOptions.jvmArgs.addAll( ["--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"] )
}
tasks.compileTestJava.configure {
options.release = gradle.ext.javaVersions.test.release.asInt()
// Needs add-opens because of https://github.com/gradle/gradle/issues/15538
options.forkOptions.jvmArgs.addAll( ["--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"] )
}
// Configure version of Java tools
java {
toolchain {
languageVersion = gradle.ext.javaVersions.main.compiler
}
}
tasks.compileTestJava {
javaCompiler = javaToolchains.compilerFor {
languageVersion = gradle.ext.javaVersions.test.compiler
}
}
// Configure JVM Options
// Display version of Java tools
tasks.withType( JavaCompile ).configureEach {
options.forkOptions.jvmArgs.addAll( getProperty( 'toolchain.compiler.jvmargs' ).toString().split( ' ' ) )
doFirst {
logger.lifecycle "Compiling with '${javaCompiler.get().metadata.installationPath}'"
}
}
tasks.withType( Javadoc ).configureEach {
options.setJFlags( getProperty( 'toolchain.javadoc.jvmargs' ).toString().split( ' ' ).toList().findAll( { !it.isEmpty() } ) )
doFirst {
logger.lifecycle "Generating javadoc with '${javadocTool.get().metadata.installationPath}'"
}
}
}
task compile(dependsOn: [compileJava, processResources, compileTestJava, processTestResources] ) task compile(dependsOn: [compileJava, processResources, compileTestJava, processTestResources] )
@ -231,7 +178,7 @@ if ( toolsJar.exists() ) {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Testing // Testing
if ( gradle.ext.javaToolchainEnabled ) { if ( jdkVersions.explicitlyConfigured ) {
tasks.test { tasks.test {
// Configure version of Java tools // Configure version of Java tools
javaLauncher = javaToolchains.launcherFor { javaLauncher = javaToolchains.launcherFor {
@ -363,7 +310,7 @@ test {
// and those classes always have bytecode matching the version of the launcher. // and those classes always have bytecode matching the version of the launcher.
// So for example, when using a JDK22 launcher and compiling tests with --release 21, // So for example, when using a JDK22 launcher and compiling tests with --release 21,
// Bytebuddy will still encounter classes with Java 22 bytecode. // Bytebuddy will still encounter classes with Java 22 bytecode.
if ( gradle.ext.javaVersions.test.launcher.asInt() >= 22 ) { if ( jdkVersions.test.launcher.asInt() >= 22 ) {
logger.warn( "The version of Java bytecode that will be tested is not supported by Bytebuddy by default. " + logger.warn( "The version of Java bytecode that will be tested is not supported by Bytebuddy by default. " +
" Setting 'net.bytebuddy.experimental=true'." ) " Setting 'net.bytebuddy.experimental=true'." )
systemProperty 'net.bytebuddy.experimental', true systemProperty 'net.bytebuddy.experimental', true
@ -537,7 +484,7 @@ task forbiddenApisSystemOut(type: CheckForbiddenApis, dependsOn: compileJava) {
} }
task forbiddenApisUnsafe(type: CheckForbiddenApis, dependsOn: compileJava) { task forbiddenApisUnsafe(type: CheckForbiddenApis, dependsOn: compileJava) {
bundledSignatures += "jdk-unsafe-${gradle.ext.baselineJavaVersion}".toString() bundledSignatures += "jdk-unsafe-${jdkVersions.baseline}".toString()
// unfortunately we currently have many uses of default Locale implicitly (~370) which need to be fixed // unfortunately we currently have many uses of default Locale implicitly (~370) which need to be fixed
// before we can fully enabled this check // before we can fully enabled this check

View File

@ -254,7 +254,7 @@ tasks.withType( Test.class ).each { test ->
} }
// Tests with records // Tests with records
if ( gradle.ext.javaVersions.test.release.asInt() >= 17 && gradle.ext.javaToolchainEnabled ) { if ( jdkVersions.test.release.asInt() >= 17 && jdkVersions.explicit ) {
// Add a new source set, which contains tests that can run on JDK17+ // Add a new source set, which contains tests that can run on JDK17+
sourceSets { sourceSets {

View File

@ -68,6 +68,14 @@ gradlePlugin {
id = 'org.hibernate.orm.build.properties' id = 'org.hibernate.orm.build.properties'
implementationClass = 'org.hibernate.orm.properties.ConfigPropertyCollectorPlugin' implementationClass = 'org.hibernate.orm.properties.ConfigPropertyCollectorPlugin'
} }
jdkVersionsPlugin {
id = 'org.hibernate.orm.build.jdks'
implementationClass = 'org.hibernate.orm.toolchains.JdkVersionPlugin'
}
javaModulePlugin {
id = 'org.hibernate.orm.build.java-module'
implementationClass = 'org.hibernate.orm.toolchains.JavaModulePlugin'
}
} }
} }

View File

@ -0,0 +1,151 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.toolchains;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.JavaVersion;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
import org.gradle.jvm.toolchain.JavaToolchainService;
import org.gradle.jvm.toolchain.JavaToolchainSpec;
import static java.util.Arrays.asList;
/**
* @author Steve Ebersole
*/
public class JavaModulePlugin implements Plugin<Project> {
private final JavaToolchainService toolchainService;
@Inject
public JavaModulePlugin(JavaToolchainService toolchainService) {
this.toolchainService = toolchainService;
}
@Override
public void apply(Project project) {
project.getPluginManager().apply( JdkVersionPlugin.class );
final JdkVersionConfig jdkVersionsConfig = project.getExtensions().getByType( JdkVersionConfig.class );
final JavaPluginExtension javaPluginExtension = project.getExtensions().getByType( JavaPluginExtension.class );
final SourceSetContainer sourceSets = javaPluginExtension.getSourceSets();
final SourceSet mainSourceSet = sourceSets.getByName( SourceSet.MAIN_SOURCE_SET_NAME );
final SourceSet testSourceSet = sourceSets.getByName( SourceSet.TEST_SOURCE_SET_NAME );
final JavaCompile mainCompileTask = (JavaCompile) project.getTasks().getByName( mainSourceSet.getCompileJavaTaskName() );
mainCompileTask.setSourceCompatibility( jdkVersionsConfig.getTestCompileVersion().toString() );
mainCompileTask.setTargetCompatibility( jdkVersionsConfig.getTestCompileVersion().toString() );
final JavaCompile testCompileTask = (JavaCompile) project.getTasks().getByName( testSourceSet.getCompileJavaTaskName() );
testCompileTask.setSourceCompatibility( jdkVersionsConfig.getTestCompileVersion().toString() );
testCompileTask.setTargetCompatibility( jdkVersionsConfig.getTestCompileVersion().toString() );
if ( jdkVersionsConfig.isExplicit() ) {
javaPluginExtension.getToolchain().getLanguageVersion().set( jdkVersionsConfig.getMainCompileVersion() );
prepareCompileTask( mainCompileTask, jdkVersionsConfig.getMainCompileVersion() );
prepareCompileTask( testCompileTask, jdkVersionsConfig.getTestCompileVersion() );
testCompileTask.getJavaCompiler().set(
toolchainService.compilerFor( new Action<JavaToolchainSpec>() {
@Override
public void execute(JavaToolchainSpec javaToolchainSpec) {
javaToolchainSpec.getLanguageVersion().set( jdkVersionsConfig.getTestCompileVersion() );
}
} )
);
project.getTasks().withType( JavaCompile.class ).configureEach( new Action<JavaCompile>() {
@Override
public void execute(JavaCompile compileTask) {
getJvmArgs( compileTask ).addAll(
Arrays.asList(
project.property( "toolchain.compiler.jvmargs" ).toString().split( " " )
)
);
compileTask.doFirst(
new Action<Task>() {
@Override
public void execute(Task task) {
project.getLogger().lifecycle(
"Compiling with '%s'",
compileTask.getJavaCompiler().get().getMetadata().getInstallationPath()
);
}
}
);
}
} );
project.getTasks().withType( Javadoc.class ).configureEach( (javadocTask) -> {
javadocTask.getOptions().setJFlags( javadocFlags( project ) );
javadocTask.doFirst( new Action<Task>() {
@Override
public void execute(Task task) {
project.getLogger().lifecycle(
"Generating javadoc with '%s'",
javadocTask.getJavadocTool().get().getMetadata().getInstallationPath()
);
}
} );
} );
}
}
private static List<String> javadocFlags(Project project) {
final String jvmArgs = project.property( "toolchain.javadoc.jvmargs" ).toString();
final String[] splits = jvmArgs.split( " " );
return Arrays.asList( splits ).stream().filter( (split) -> !split.isEmpty() ).collect( Collectors.toList() );
}
private void prepareCompileTask(JavaCompile compileTask, JavaLanguageVersion version) {
compileTask.getJavaCompiler().set(
toolchainService.compilerFor( new Action<JavaToolchainSpec>() {
@Override
public void execute(JavaToolchainSpec javaToolchainSpec) {
javaToolchainSpec.getLanguageVersion().set( version );
}
} )
);
compileTask.getOptions().getRelease().set( version.asInt() );
// Needs add-opens because of https://github.com/gradle/gradle/issues/15538
getJvmArgs( compileTask ).addAll( asList( "--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED" ) );
}
public static List<String> getJvmArgs(JavaCompile compileTask) {
final List<String> existing = compileTask
.getOptions()
.getForkOptions()
.getJvmArgs();
if ( existing == null ) {
final List<String> target = new ArrayList<>();
compileTask.getOptions().getForkOptions().setJvmArgs( target );
return target;
}
else {
return existing;
}
}
}

View File

@ -0,0 +1,286 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.toolchains;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.gradle.StartParameter;
import org.gradle.api.Project;
import org.gradle.api.artifacts.VersionCatalog;
import org.gradle.api.artifacts.VersionConstraint;
import org.gradle.api.initialization.Settings;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
import org.jetbrains.annotations.NotNull;
import static java.util.Objects.requireNonNullElse;
/**
* Describes the JDK versions of interest to the Hibernate build
*
* @author Steve Ebersole
*/
public class JdkVersionConfig {
public static final String DSL_NAME = "jdkVersions";
public static final String MAIN_JDK_VERSION = "main.jdk.version";
public static final String TEST_JDK_VERSION = "test.jdk.version";
private final boolean explicit;
private final JavaLanguageVersion baseline;
private final MainJdks main;
private final TestJdks test;
public JdkVersionConfig(
boolean explicit,
JavaLanguageVersion baseline,
JavaLanguageVersion mainCompileVersion,
JavaLanguageVersion mainReleaseVersion,
JavaLanguageVersion testCompileVersion,
JavaLanguageVersion testReleaseVersion,
JavaLanguageVersion testLauncherVersion) {
this.explicit = explicit;
this.baseline = baseline;
this.main = new MainJdks( mainCompileVersion, mainReleaseVersion );
this.test = new TestJdks( testCompileVersion, testReleaseVersion, testLauncherVersion );
}
public boolean isExplicitlyConfigured() {
return explicit;
}
public boolean isExplicit() {
return explicit;
}
public JavaLanguageVersion getBaselineVersion() {
return baseline;
}
public JavaLanguageVersion getBaseline() {
return baseline;
}
public MainJdks getMain() {
return main;
}
public TestJdks getTest() {
return test;
}
public JavaLanguageVersion getMainCompileVersion() {
return main.getCompile();
}
public JavaLanguageVersion getMainReleaseVersion() {
return main.getRelease();
}
public JavaLanguageVersion getTestCompileVersion() {
return test.getCompile();
}
public JavaLanguageVersion getTestReleaseVersion() {
return test.getRelease();
}
public JavaLanguageVersion getTestLauncherVersion() {
return test.getLauncher();
}
public Set<JavaLanguageVersion> getAllVersions() {
final HashSet<JavaLanguageVersion> versions = new HashSet<>();
versions.add( getMainCompileVersion() );
versions.add( getMainReleaseVersion() );
versions.add( getTestCompileVersion() );
versions.add( getTestReleaseVersion() );
versions.add( getTestLauncherVersion() );
return versions;
}
@NotNull
public static JdkVersionConfig createVersionConfig(
JavaLanguageVersion explicitMainVersion,
JavaLanguageVersion explicitTestVersion,
JavaLanguageVersion gradleJdkVersion,
JavaLanguageVersion baselineJdkVersion,
JavaLanguageVersion maxSupportedJdkVersion) {
final boolean explicitlyConfigured = explicitMainVersion != null || explicitTestVersion != null;
final JavaLanguageVersion mainCompileVersion;
final JavaLanguageVersion mainReleaseVersion;
final JavaLanguageVersion testCompileVersion;
final JavaLanguageVersion testReleaseVersion;
final JavaLanguageVersion testLauncherVersion;
if ( explicitlyConfigured ) {
mainCompileVersion = requireNonNullElse( explicitMainVersion, baselineJdkVersion );
testCompileVersion = requireNonNullElse( explicitTestVersion, baselineJdkVersion );
mainReleaseVersion = baselineJdkVersion;
if ( testCompileVersion.asInt() > gradleJdkVersion.asInt() ) {
System.out.println(
"[WARN] Gradle does not support bytecode version '${testCompilerVersion}'."
+ " Forcing test bytecode to version ${GRADLE_MAX_SUPPORTED_BYTECODE_VERSION}."
);
testReleaseVersion = maxSupportedJdkVersion;
}
else {
testReleaseVersion = testCompileVersion;
}
testLauncherVersion = testCompileVersion;
return new JdkVersionConfig(
false,
baselineJdkVersion,
mainCompileVersion,
mainReleaseVersion,
testCompileVersion,
testReleaseVersion,
testLauncherVersion
);
}
else {
// Not testing a particular JDK version: we will use the same JDK used to run Gradle.
// We disable toolchains for convenience, so that anyone can just run the build with their own JDK
// without any additional options and without downloading the whole JDK.
if ( gradleJdkVersion.asInt() > maxSupportedJdkVersion.asInt() ) {
System.out.println(
"[WARN] Gradle does not support this JDK, because it is too recent; build is likely to fail."
+ " To avoid failures, you should use an older Java version when running Gradle, and rely on toolchains."
+ " To that end, specify the version of Java you want to run tests with using property 'test.jdk.version',"
+ " and specify the path to JDK8 *and* a JDK of the test version using property 'org.gradle.java.installations.paths'."
+ " Example:"
+ " ./gradlew build -Ptest.jdk.version=15 -Porg.gradle.java.installations.paths=$SDKMAN_CANDIDATES_DIR/java/15.0.1-open,$SDKMAN_CANDIDATES_DIR/java/8"
);
}
return new JdkVersionConfig(
false,
baselineJdkVersion,
gradleJdkVersion,
baselineJdkVersion,
gradleJdkVersion,
baselineJdkVersion,
gradleJdkVersion
);
}
}
@NotNull
private static JavaLanguageVersion getJavaLanguageVersion(VersionCatalog jdks, String entryName) {
final VersionConstraint versionConstraint = jdks.findVersion( entryName ).orElseThrow();
return JavaLanguageVersion.of( versionConstraint.getRequiredVersion() );
}
public static JavaLanguageVersion extractVersion(Settings settings, String propertyName) {
final StartParameter startParameters = settings.getGradle().getStartParameter();
final String projectProp = startParameters.getProjectProperties().get( propertyName );
if ( projectProp != null ) {
return JavaLanguageVersion.of( projectProp );
}
final String sysProp = startParameters.getSystemPropertiesArgs().get( propertyName );
if ( sysProp != null ) {
return JavaLanguageVersion.of( sysProp );
}
return null;
}
public static JavaLanguageVersion extractVersion(Project project, String propertyName) {
final Object projectProp = project.getProperties().get( propertyName );
if ( projectProp != null ) {
return JavaLanguageVersion.of( projectProp.toString() );
}
final Object sysProp = System.getProperties().get( propertyName );
if ( sysProp != null ) {
return JavaLanguageVersion.of( sysProp.toString() );
}
return null;
}
public static class MainJdks implements JdkVersionCombo {
private final JavaLanguageVersion compileVersion;
private final JavaLanguageVersion releaseVersion;
public MainJdks(JavaLanguageVersion compileVersion, JavaLanguageVersion releaseVersion) {
this.compileVersion = compileVersion;
this.releaseVersion = releaseVersion;
}
@Override
public JavaLanguageVersion getCompile() {
return compileVersion;
}
public JavaLanguageVersion getCompiler() {
return compileVersion;
}
@Override
public JavaLanguageVersion getRelease() {
return releaseVersion;
}
@Override
public String toString() {
return "[compile: " + compileVersion + ", release:" + releaseVersion + "]";
}
}
public static class TestJdks implements JdkVersionCombo {
private final JavaLanguageVersion compileVersion;
private final JavaLanguageVersion releaseVersion;
private final JavaLanguageVersion launcherVersion;
public TestJdks(
JavaLanguageVersion compileVersion,
JavaLanguageVersion releaseVersion,
JavaLanguageVersion launcherVersion) {
this.compileVersion = compileVersion;
this.releaseVersion = releaseVersion;
this.launcherVersion = launcherVersion;
}
public JavaLanguageVersion getCompiler() {
return compileVersion;
}
@Override
public JavaLanguageVersion getCompile() {
return compileVersion;
}
@Override
public JavaLanguageVersion getRelease() {
return releaseVersion;
}
public JavaLanguageVersion getLauncher() {
return launcherVersion;
}
@Override
public String toString() {
return "[compile: " + compileVersion + ", release:" + releaseVersion + ", launcher: " + launcherVersion + "]";
}
}
public interface JdkVersionCombo {
JavaLanguageVersion getCompile();
JavaLanguageVersion getRelease();
}
}

View File

@ -0,0 +1,72 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.toolchains;
import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.JavaVersion;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.VersionCatalog;
import org.gradle.api.artifacts.VersionCatalogsExtension;
import org.gradle.api.artifacts.VersionConstraint;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
import org.gradle.jvm.toolchain.JavaToolchainService;
import org.gradle.jvm.toolchain.JavaToolchainSpec;
import org.jetbrains.annotations.NotNull;
import static org.hibernate.orm.toolchains.JdkVersionConfig.MAIN_JDK_VERSION;
import static org.hibernate.orm.toolchains.JdkVersionConfig.TEST_JDK_VERSION;
import static org.hibernate.orm.toolchains.JdkVersionConfig.createVersionConfig;
import static org.hibernate.orm.toolchains.JdkVersionConfig.extractVersion;
/**
* @author Steve Ebersole
*/
public class JdkVersionPlugin implements Plugin<Project> {
private final JavaToolchainService toolchainService;
@Inject
public JdkVersionPlugin(JavaToolchainService toolchainService) {
this.toolchainService = toolchainService;
}
@Override
public void apply(Project project) {
final JavaLanguageVersion explicitMainVersion = extractVersion( project, MAIN_JDK_VERSION );
final JavaLanguageVersion explicitTestVersion = extractVersion( project, TEST_JDK_VERSION );
final JavaLanguageVersion gradleJdkVersion = JavaLanguageVersion.of( JavaVersion.current().getMajorVersion() );
final VersionCatalogsExtension versionCatalogs = project.getExtensions().getByType( VersionCatalogsExtension.class );
final VersionCatalog jdkVersions = versionCatalogs.named( "jdks" );
final JavaLanguageVersion baselineJdkVersion = getJavaLanguageVersion( jdkVersions, "baseline" );
final JavaLanguageVersion maxSupportedJdkVersion = getJavaLanguageVersion( jdkVersions, "maxSupportedBytecode" );
final JdkVersionConfig jdkVersionConfig = createVersionConfig(
explicitMainVersion,
explicitTestVersion,
gradleJdkVersion,
baselineJdkVersion,
maxSupportedJdkVersion
);
project.getExtensions().add( JdkVersionConfig.DSL_NAME, jdkVersionConfig );
JdkVersionsLogging.logVersions( jdkVersionConfig );
}
@NotNull
private static JavaLanguageVersion getJavaLanguageVersion(VersionCatalog jdks, String entryName) {
final VersionConstraint versionConstraint = jdks.findVersion( entryName ).orElseThrow();
return JavaLanguageVersion.of( versionConstraint.getRequiredVersion() );
}
}

View File

@ -0,0 +1,60 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.toolchains;
import org.gradle.api.JavaVersion;
import org.gradle.api.Plugin;
import org.gradle.api.artifacts.VersionCatalog;
import org.gradle.api.artifacts.VersionConstraint;
import org.gradle.api.initialization.Settings;
import org.gradle.api.plugins.ExtraPropertiesExtension;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
import org.jetbrains.annotations.NotNull;
import static org.hibernate.orm.toolchains.JdkVersionConfig.MAIN_JDK_VERSION;
import static org.hibernate.orm.toolchains.JdkVersionConfig.TEST_JDK_VERSION;
import static org.hibernate.orm.toolchains.JdkVersionConfig.createVersionConfig;
import static org.hibernate.orm.toolchains.JdkVersionConfig.extractVersion;
/**
* @author Steve Ebersole
*/
public class JdkVersionSettingsPlugin implements Plugin<Settings> {
@Override
public void apply(Settings settings) {
final JavaLanguageVersion explicitMainVersion = extractVersion( settings, MAIN_JDK_VERSION );
final JavaLanguageVersion explicitTestVersion = extractVersion( settings, TEST_JDK_VERSION );
final JavaLanguageVersion gradleJdkVersion = JavaLanguageVersion.of( JavaVersion.current().getMajorVersion() );
final JavaLanguageVersion baselineJdkVersion;
final JavaLanguageVersion maxSupportedJdkVersion;
// final VersionCatalogsExtension versionCatalogs = settings.getExtensions().getByType( VersionCatalogsExtension.class );
// final VersionCatalog jdkVersions = versionCatalogs.named( "jdks" );
// baselineJdkVersion = getJavaLanguageVersion( jdkVersions, "baseline" );
// maxSupportedJdkVersion = getJavaLanguageVersion( jdkVersions, "maxSupportedBytecode" );
baselineJdkVersion = JavaLanguageVersion.of( "11" );
maxSupportedJdkVersion = JavaLanguageVersion.of( "17" );
final JdkVersionConfig jdkVersionConfig = createVersionConfig(
explicitMainVersion,
explicitTestVersion,
gradleJdkVersion,
baselineJdkVersion,
maxSupportedJdkVersion
);
settings.getGradle().getExtensions().add( JdkVersionConfig.DSL_NAME, jdkVersionConfig );
JdkVersionsLogging.logVersions( jdkVersionConfig );
}
@NotNull
private static JavaLanguageVersion getJavaLanguageVersion(VersionCatalog jdks, String entryName) {
final VersionConstraint versionConstraint = jdks.findVersion( entryName ).orElseThrow();
return JavaLanguageVersion.of( versionConstraint.getRequiredVersion() );
}
}

View File

@ -0,0 +1,43 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.toolchains;
/**
* @author Steve Ebersole
*/
public class JdkVersionsLogging {
private static boolean logged = false;
public static void logVersions(JdkVersionConfig jdkVersionConfig) {
if ( logged ) {
return;
}
logged = true;
final String implicitExplicitString = jdkVersionConfig.isExplicit() ? "explicit" : "implicit";
System.out.println(
"Java versions for main code: " + jdkVersionConfig.getMain()
+ " (" + implicitExplicitString + ")"
);
System.out.println(
"Java versions for test code: " + jdkVersionConfig.getTest()
+ " (" + implicitExplicitString + ")"
);
}
public static void logOnce(String message) {
if ( logged ) {
return;
}
logged = true;
System.out.println( message );
}
}

View File

@ -12,6 +12,7 @@ import groovy.json.JsonSlurper
apply from: rootProject.file( 'gradle/module.gradle' ) apply from: rootProject.file( 'gradle/module.gradle' )
apply plugin: 'org.hibernate.orm.build.doc-pub' apply plugin: 'org.hibernate.orm.build.doc-pub'
apply plugin: 'org.hibernate.orm.build.jdks'
apply plugin: 'idea' apply plugin: 'idea'
idea.module { idea.module {
@ -193,13 +194,13 @@ task aggregateJavadocs(type: Javadoc) {
options.addStringOption( 'Xdoclint:none', '-quiet' ) options.addStringOption( 'Xdoclint:none', '-quiet' )
if ( gradle.ext.javaToolchainEnabled ) { if ( jdkVersions.explicit ) {
options.setJFlags( getProperty( 'toolchain.javadoc.jvmargs' ).toString(). options.setJFlags( getProperty( 'toolchain.javadoc.jvmargs' ).toString().
split( ' ' ).toList().findAll( { !it.isEmpty() } ) ) split( ' ' ).toList().findAll( { !it.isEmpty() } ) )
} }
} }
if ( gradle.ext.javaToolchainEnabled ) { if ( jdkVersions.explicit ) {
// Display version of Java tools // Display version of Java tools
doFirst { doFirst {
if ( javadocTool.present ) { if ( javadocTool.present ) {

View File

@ -51,6 +51,13 @@ dependencyResolutionManagement {
} }
versionCatalogs { versionCatalogs {
jdks {
version( "baseline", "11" )
// Gradle does bytecode transformation on tests.
// You can't use bytecode higher than what Gradle supports, even with toolchains.
version( "maxSupportedBytecode", "21" )
}
libs { libs {
def antlrVersion = "4.10.1" def antlrVersion = "4.10.1"
def byteBuddyVersion = "1.14.7" def byteBuddyVersion = "1.14.7"
@ -278,79 +285,6 @@ buildCache {
} }
} }
gradle.ext.baselineJavaVersion = JavaLanguageVersion.of( 11 )
// Gradle does bytecode transformation on tests.
// You can't use bytecode higher than what Gradle supports, even with toolchains.
def GRADLE_MAX_SUPPORTED_BYTECODE_VERSION = 21
// If either 'main.jdk.version' or 'test.jdk.version' is set, enable the toolchain and use the selected jdk.
// If only one property is set, the other defaults to the baseline Java version (11).
// Note that when toolchain is enabled, you also need to specify
// the location of the selected jdks
// (auto-download and auto-detect are disabled in gradle.properties).
//
// Example (with SDKMAN):
// ./gradlew build -Ptest.jdk.version=15 \
// -Porg.gradle.java.installations.paths=$SDKMAN_CANDIDATES_DIR/java/15.0.1-open,$SDKMAN_CANDIDATES_DIR/java/8
if ( hasProperty( 'main.jdk.version' ) || hasProperty( 'test.jdk.version' ) ) {
// Testing a particular JDK version
// Gradle doesn't support all JDK versions unless we use toolchains
gradle.ext.javaToolchainEnabled = true
gradle.ext.javaVersions = [
main: [
compiler: JavaLanguageVersion.of( hasProperty( 'main.jdk.version' )
? getProperty( 'main.jdk.version' ) : gradle.ext.baselineJavaVersion.asInt() ),
release: gradle.ext.baselineJavaVersion
],
test: [
compiler: JavaLanguageVersion.of( hasProperty( 'test.jdk.version' )
? getProperty( 'test.jdk.version' ) : gradle.ext.baselineJavaVersion.asInt() )
]
]
def testCompilerVersion = gradle.ext.javaVersions.test.compiler
if ( testCompilerVersion.asInt() > GRADLE_MAX_SUPPORTED_BYTECODE_VERSION ) {
logger.warn( "[WARN] Gradle does not support bytecode version '${testCompilerVersion}'." +
" Forcing test bytecode to version ${GRADLE_MAX_SUPPORTED_BYTECODE_VERSION}." )
gradle.ext.javaVersions.test.release = JavaLanguageVersion.of( GRADLE_MAX_SUPPORTED_BYTECODE_VERSION )
}
else {
gradle.ext.javaVersions.test.release = testCompilerVersion
}
gradle.ext.javaVersions.test.launcher = testCompilerVersion
}
else {
// Not testing a particular JDK version: we will use the same JDK used to run Gradle.
// We disable toolchains for convenience, so that anyone can just run the build with their own JDK
// without any additional options and without downloading the whole JDK.
gradle.ext.javaToolchainEnabled = false
def gradleJdkVersion = JavaLanguageVersion.of( JavaVersion.current().getMajorVersion() )
if ( gradleJdkVersion.asInt() > GRADLE_MAX_SUPPORTED_BYTECODE_VERSION ) {
logger.warn( "[WARN] Gradle does not support this JDK, because it is too recent; build is likely to fail." +
" To avoid failures, you should use an older Java version when running Gradle, and rely on toolchains." +
" To that end, specify the version of Java you want to run tests with using property 'test.jdk.version'," +
" and specify the path to JDK8 *and* a JDK of the test version using property 'org.gradle.java.installations.paths'." +
" Example:" +
"./gradlew build -Ptest.jdk.version=15 -Porg.gradle.java.installations.paths=\$SDKMAN_CANDIDATES_DIR/java/15.0.1-open,\$SDKMAN_CANDIDATES_DIR/java/8" )
}
gradle.ext.javaVersions = [
main: [
compiler: gradleJdkVersion,
release: gradle.ext.baselineJavaVersion
],
test: [
compiler: gradleJdkVersion,
release: JavaLanguageVersion.of(
Math.min( GRADLE_MAX_SUPPORTED_BYTECODE_VERSION, gradleJdkVersion.asInt() ) ),
launcher: gradleJdkVersion
]
]
}
logger.lifecycle "Java versions for main code: " + gradle.ext.javaVersions.main
logger.lifecycle "Java versions for tests: " + gradle.ext.javaVersions.test
include 'hibernate-core' include 'hibernate-core'
include 'hibernate-testing' include 'hibernate-testing'

View File

@ -15,6 +15,8 @@ plugins {
// for local publishing // for local publishing
id 'maven-publish' id 'maven-publish'
id 'org.hibernate.orm.build.jdks'
} }
apply from: rootProject.file( 'gradle/module.gradle' ) apply from: rootProject.file( 'gradle/module.gradle' )
@ -125,10 +127,10 @@ tasks.withType( JavaCompile ) {
options.encoding = 'UTF-8' options.encoding = 'UTF-8'
} }
if ( !gradle.ext.javaToolchainEnabled ) { if ( !jdkVersions.explicit ) {
tasks.withType( GroovyCompile ) { tasks.withType( GroovyCompile ) {
sourceCompatibility = JavaVersion.toVersion( gradle.ext.baselineJavaVersion ) sourceCompatibility = JavaVersion.toVersion( gradle.jdkVersions.baseline )
targetCompatibility = JavaVersion.toVersion( gradle.ext.baselineJavaVersion ) targetCompatibility = JavaVersion.toVersion( gradle.jdkVersions.baseline )
} }
} }
else { else {

View File

@ -44,12 +44,12 @@ compileTestJava {
// Tests with records // Tests with records
if ( gradle.ext.javaVersions.test.release.asInt() >= 17 && gradle.ext.javaToolchainEnabled ) { if ( jdkVersions.test.release.asInt() >= 17 && jdkVersions.explicit ) {
// We need to configure the source and target version to 17 // We need to configure the source and target version to 17
//compileTestJava17Java { //compileTestJava17Java {
compileTestJava { compileTestJava {
javaCompiler = javaToolchains.compilerFor { javaCompiler = javaToolchains.compilerFor {
languageVersion = gradle.ext.javaVersions.test.compiler languageVersion = gradle.jdkVersions.test.compile
} }
sourceCompatibility = 17 sourceCompatibility = 17
targetCompatibility = 17 targetCompatibility = 17