diff --git a/build.gradle b/build.gradle index e7671f6d014e..b1dfde00bd67 100644 --- a/build.gradle +++ b/build.gradle @@ -310,14 +310,13 @@ configure([rootProject] + javaProjects) { project -> apply plugin: "java-test-fixtures" apply plugin: "checkstyle" apply plugin: 'org.springframework.build.compile' - apply from: "${rootDir}/gradle/custom-java-home.gradle" + apply from: "${rootDir}/gradle/toolchains.gradle" apply from: "${rootDir}/gradle/ide.gradle" pluginManager.withPlugin("kotlin") { apply plugin: "org.jetbrains.dokka" compileKotlin { kotlinOptions { - jvmTarget = "1.8" languageVersion = "1.3" apiVersion = "1.3" freeCompilerArgs = ["-Xjsr305=strict"] @@ -326,7 +325,6 @@ configure([rootProject] + javaProjects) { project -> } compileTestKotlin { kotlinOptions { - jvmTarget = "1.8" freeCompilerArgs = ["-Xjsr305=strict"] } } diff --git a/buildSrc/README.md b/buildSrc/README.md index f48339e6d61f..ada387cf7144 100644 --- a/buildSrc/README.md +++ b/buildSrc/README.md @@ -8,16 +8,10 @@ They are declared in the `build.gradle` file in this folder. ### Compiler conventions The `org.springframework.build.compile` plugin applies the Java compiler conventions to the build. -By default, the build compiles sources with Java `1.8` source and target compatibility. -You can test a different source compatibility version on the CLI with a project property like: - -``` -./gradlew test -PjavaSourceVersion=11 -``` ## Build Plugins -## Optional dependencies +### Optional dependencies The `org.springframework.build.optional-dependencies` plugin creates a new `optional` Gradle configuration - it adds the dependencies to the project's compile and runtime classpath @@ -25,7 +19,7 @@ but doesn't affect the classpath of dependent projects. This plugin does not provide a `provided` configuration, as the native `compileOnly` and `testCompileOnly` configurations are preferred. -## API Diff +### API Diff This plugin uses the [Gradle JApiCmp](https://github.com/melix/japicmp-gradle-plugin) plugin to generate API Diff reports for each Spring Framework module. This plugin is applied once on the root diff --git a/buildSrc/src/main/java/org/springframework/build/compile/CompilerConventionsPlugin.java b/buildSrc/src/main/java/org/springframework/build/compile/CompilerConventionsPlugin.java index db51666f74b5..5284df28f124 100644 --- a/buildSrc/src/main/java/org/springframework/build/compile/CompilerConventionsPlugin.java +++ b/buildSrc/src/main/java/org/springframework/build/compile/CompilerConventionsPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,31 +20,21 @@ import java.util.Arrays; import java.util.List; -import org.gradle.api.JavaVersion; import org.gradle.api.Plugin; import org.gradle.api.Project; +import org.gradle.api.plugins.JavaLibraryPlugin; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.tasks.compile.JavaCompile; /** * {@link Plugin} that applies conventions for compiling Java sources in Spring Framework. - *

One can override the default Java source compatibility version - * with a dedicated property on the CLI: {@code "./gradlew test -PjavaSourceVersion=11"}. * * @author Brian Clozel * @author Sam Brannen */ public class CompilerConventionsPlugin implements Plugin { - /** - * The project property that can be used to switch the Java source - * compatibility version for building source and test classes. - */ - public static final String JAVA_SOURCE_VERSION_PROPERTY = "javaSourceVersion"; - - public static final JavaVersion DEFAULT_COMPILER_VERSION = JavaVersion.VERSION_1_8; - private static final List COMPILER_ARGS; private static final List TEST_COMPILER_ARGS; @@ -69,7 +59,7 @@ public class CompilerConventionsPlugin implements Plugin { @Override public void apply(Project project) { - project.getPlugins().withType(JavaPlugin.class, javaPlugin -> applyJavaCompileConventions(project)); + project.getPlugins().withType(JavaLibraryPlugin.class, javaPlugin -> applyJavaCompileConventions(project)); } /** @@ -79,15 +69,6 @@ public void apply(Project project) { */ private void applyJavaCompileConventions(Project project) { JavaPluginConvention java = project.getConvention().getPlugin(JavaPluginConvention.class); - if (project.hasProperty(JAVA_SOURCE_VERSION_PROPERTY)) { - JavaVersion javaSourceVersion = JavaVersion.toVersion(project.property(JAVA_SOURCE_VERSION_PROPERTY)); - java.setSourceCompatibility(javaSourceVersion); - } - else { - java.setSourceCompatibility(DEFAULT_COMPILER_VERSION); - } - java.setTargetCompatibility(DEFAULT_COMPILER_VERSION); - project.getTasks().withType(JavaCompile.class) .matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME)) .forEach(compileTask -> { diff --git a/ci/images/ci-image-jdk11/Dockerfile b/ci/images/ci-image-jdk11/Dockerfile deleted file mode 100644 index 6de48e0f1cbc..000000000000 --- a/ci/images/ci-image-jdk11/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM ubuntu:focal-20210119 - -ADD setup.sh /setup.sh -ADD get-jdk-url.sh /get-jdk-url.sh -RUN ./setup.sh java11 - -ENV JAVA_HOME /opt/openjdk -ENV PATH $JAVA_HOME/bin:$PATH diff --git a/ci/images/ci-image-jdk15/Dockerfile b/ci/images/ci-image-jdk15/Dockerfile deleted file mode 100644 index 71b47fbe07a7..000000000000 --- a/ci/images/ci-image-jdk15/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM ubuntu:focal-20210119 - -ADD setup.sh /setup.sh -ADD get-jdk-url.sh /get-jdk-url.sh -RUN ./setup.sh java15 - -ENV JAVA_HOME /opt/openjdk -ENV PATH $JAVA_HOME/bin:$PATH diff --git a/ci/images/ci-image/Dockerfile b/ci/images/ci-image/Dockerfile index 2952402431ac..1ce41f37a932 100644 --- a/ci/images/ci-image/Dockerfile +++ b/ci/images/ci-image/Dockerfile @@ -4,5 +4,8 @@ ADD setup.sh /setup.sh ADD get-jdk-url.sh /get-jdk-url.sh RUN ./setup.sh java8 -ENV JAVA_HOME /opt/openjdk +ENV JAVA_HOME /opt/openjdk/java8 +ENV JDK11 /opt/openjdk/java11 +ENV JDK15 /opt/openjdk/java15 + ENV PATH $JAVA_HOME/bin:$PATH diff --git a/ci/images/setup.sh b/ci/images/setup.sh index 87c3fbc2cc77..1fca196502dc 100755 --- a/ci/images/setup.sh +++ b/ci/images/setup.sh @@ -19,13 +19,20 @@ curl --output /opt/concourse-release-scripts.jar https://repo.spring.io/release/ ########################################################### # JAVA ########################################################### -JDK_URL=$( ./get-jdk-url.sh $1 ) mkdir -p /opt/openjdk -cd /opt/openjdk -curl -L ${JDK_URL} | tar zx --strip-components=1 -test -f /opt/openjdk/bin/java -test -f /opt/openjdk/bin/javac +pushd /opt/openjdk > /dev/null +for jdk in java8 java11 java15 +do + JDK_URL=$( /get-jdk-url.sh $jdk ) + mkdir $jdk + pushd $jdk > /dev/null + curl -L ${JDK_URL} | tar zx --strip-components=1 + test -f bin/java + test -f bin/javac + popd > /dev/null +done +popd ########################################################### # GRADLE ENTERPRISE diff --git a/ci/pipeline.yml b/ci/pipeline.yml index e93bed5235f0..0de0158368c4 100644 --- a/ci/pipeline.yml +++ b/ci/pipeline.yml @@ -85,18 +85,6 @@ resources: source: <<: *docker-resource-source repository: ((docker-hub-organization))/spring-framework-ci -- name: ci-image-jdk11 - type: docker-image - icon: docker - source: - <<: *docker-resource-source - repository: ((docker-hub-organization))/spring-framework-ci-jdk11 -- name: ci-image-jdk15 - type: docker-image - icon: docker - source: - <<: *docker-resource-source - repository: ((docker-hub-organization))/spring-framework-ci-jdk15 - name: artifactory-repo type: artifactory-resource icon: package-variant @@ -161,14 +149,6 @@ jobs: params: build: ci-images-git-repo/ci/images dockerfile: ci-images-git-repo/ci/images/ci-image/Dockerfile - - put: ci-image-jdk11 - params: - build: ci-images-git-repo/ci/images - dockerfile: ci-images-git-repo/ci/images/ci-image-jdk11/Dockerfile - - put: ci-image-jdk15 - params: - build: ci-images-git-repo/ci/images - dockerfile: ci-images-git-repo/ci/images/ci-image-jdk15/Dockerfile - name: build serial: true public: true @@ -227,7 +207,7 @@ jobs: serial: true public: true plan: - - get: ci-image-jdk11 + - get: ci-image - get: git-repo - get: every-morning trigger: true @@ -235,8 +215,11 @@ jobs: params: { state: "pending", commit: "git-repo" } - do: - task: check-project - image: ci-image-jdk11 + image: ci-image file: git-repo/ci/tasks/check-project.yml + params: + MAIN_TOOLCHAIN: 8 + TEST_TOOLCHAIN: 11 <<: *build-project-task-params on_failure: do: @@ -251,7 +234,7 @@ jobs: serial: true public: true plan: - - get: ci-image-jdk15 + - get: ci-image - get: git-repo - get: every-morning trigger: true @@ -259,8 +242,11 @@ jobs: params: { state: "pending", commit: "git-repo" } - do: - task: check-project - image: ci-image-jdk15 + image: ci-image file: git-repo/ci/tasks/check-project.yml + params: + MAIN_TOOLCHAIN: 8 + TEST_TOOLCHAIN: 15 <<: *build-project-task-params on_failure: do: diff --git a/ci/scripts/check-project.sh b/ci/scripts/check-project.sh index 94c4e8df65b4..f2bf454e3597 100755 --- a/ci/scripts/check-project.sh +++ b/ci/scripts/check-project.sh @@ -4,5 +4,6 @@ set -e source $(dirname $0)/common.sh pushd git-repo > /dev/null -./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 check +./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Dorg.gradle.java.installations.fromEnv=JDK11,JDK15 \ + -PmainToolchain=$MAIN_TOOLCHAIN -PtestToolchain=$TEST_TOOLCHAIN --no-daemon --max-workers=4 check popd > /dev/null diff --git a/ci/tasks/check-project.yml b/ci/tasks/check-project.yml index ea6d6ddb94c8..bea1185231b9 100644 --- a/ci/tasks/check-project.yml +++ b/ci/tasks/check-project.yml @@ -10,6 +10,8 @@ caches: params: BRANCH: CI: true + MAIN_TOOLCHAIN: + TEST_TOOLCHAIN: GRADLE_ENTERPRISE_ACCESS_KEY: GRADLE_ENTERPRISE_CACHE_USERNAME: GRADLE_ENTERPRISE_CACHE_PASSWORD: diff --git a/gradle/custom-java-home.gradle b/gradle/custom-java-home.gradle deleted file mode 100644 index 54d1de1eb8f9..000000000000 --- a/gradle/custom-java-home.gradle +++ /dev/null @@ -1,80 +0,0 @@ -// ----------------------------------------------------------------------------- -// -// This script adds support for the following two JVM system properties -// that control the build for alternative JDKs (i.e., a JDK other than -// the one used to launch the Gradle process). -// -// - customJavaHome: absolute path to the alternate JDK installation to -// use to compile Java code and execute tests. This system property -// is also used in spring-oxm.gradle to determine whether JiBX is -// supported. -// -// - customJavaSourceVersion: Java version supplied to the `--release` -// command line flag to control the Java source and target -// compatibility version. Supported versions include 9 or higher. -// Do not set this system property if Java 8 should be used. -// -// Examples: -// -// ./gradlew -DcustomJavaHome=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home test -// -// ./gradlew --no-build-cache -DcustomJavaHome=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home test -// -// ./gradlew -DcustomJavaHome=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home -DcustomJavaSourceVersion=14 test -// -// -// Credits: inspired by work from Marc Philipp and Stephane Nicoll -// -// ----------------------------------------------------------------------------- - -import org.gradle.internal.os.OperatingSystem -// import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile - -def customJavaHome = System.getProperty("customJavaHome") - -if (customJavaHome) { - def customJavaHomeDir = new File(customJavaHome) - def customJavaSourceVersion = System.getProperty("customJavaSourceVersion") - - tasks.withType(JavaCompile) { - logger.info("Java home for " + it.name + " task in " + project.name + ": " + customJavaHomeDir) - options.forkOptions.javaHome = customJavaHomeDir - inputs.property("customJavaHome", customJavaHome) - if (customJavaSourceVersion) { - options.compilerArgs += [ "--release", customJavaSourceVersion] - inputs.property("customJavaSourceVersion", customJavaSourceVersion) - } - } - - tasks.withType(GroovyCompile) { - logger.info("Java home for " + it.name + " task in " + project.name + ": " + customJavaHomeDir) - options.forkOptions.javaHome = customJavaHomeDir - inputs.property("customJavaHome", customJavaHome) - if (customJavaSourceVersion) { - options.compilerArgs += [ "--release", customJavaSourceVersion] - inputs.property("customJavaSourceVersion", customJavaSourceVersion) - } - } - - /* - tasks.withType(KotlinJvmCompile) { - logger.info("Java home for " + it.name + " task in " + project.name + ": " + customJavaHome) - kotlinOptions.jdkHome = customJavaHomeDir - inputs.property("customJavaHome", customJavaHome) - } - */ - - tasks.withType(Test) { - def javaExecutable = customJavaHome + "/bin/java" - if (OperatingSystem.current().isWindows()) { - javaExecutable += ".exe" - } - logger.info("Java executable for " + it.name + " task in " + project.name + ": " + javaExecutable) - executable = javaExecutable - inputs.property("customJavaHome", customJavaHome) - if (customJavaSourceVersion) { - inputs.property("customJavaSourceVersion", customJavaSourceVersion) - } - } - -} diff --git a/gradle/spring-module.gradle b/gradle/spring-module.gradle index 51b18007f832..49efaeae84dc 100644 --- a/gradle/spring-module.gradle +++ b/gradle/spring-module.gradle @@ -1,3 +1,4 @@ +apply plugin: 'java-library' apply plugin: 'org.springframework.build.compile' apply plugin: 'org.springframework.build.optional-dependencies' // Uncomment the following for Shadow support in the jmhJar block. diff --git a/gradle/toolchains.gradle b/gradle/toolchains.gradle new file mode 100644 index 000000000000..2ae10a0581fa --- /dev/null +++ b/gradle/toolchains.gradle @@ -0,0 +1,127 @@ +/** + * Apply the JVM Toolchain conventions + * See https://docs.gradle.org/current/userguide/toolchains.html + * + * One can choose the toolchain to use for compiling the MAIN sources and/or compiling + * and running the TEST sources. These options apply to Java, Kotlin and Groovy sources + * when available. + * {@code "./gradlew check -PmainToolchain=8 -PtestToolchain=11"} will use: + *

+ * + * Gradle will automatically detect JDK distributions in well-known locations. + * The following command will list the detected JDKs on the host. + * {@code + * $ ./gradlew -q javaToolchains + * } + * + * We can also configure ENV variables and let Gradle know about them: + * {@code + * $ echo JDK11 + * /opt/openjdk/java11 + * $ echo JDK15 + * /opt/openjdk/java15 + * $ ./gradlew -Dorg.gradle.java.installations.fromEnv=JDK11,JDK15 check + * } + * + * @author Brian Clozel + */ +def mainToolchain = 'mainToolchain' +def testToolchain = 'testToolchain' + +plugins.withType(JavaPlugin) { + // Configure the Java Toolchain if the 'mainToolchain' property is defined + if (project.hasProperty(mainToolchain)) { + def mainLanguageVersion = JavaLanguageVersion.of(project.property(mainToolchain).toString()) + java { + toolchain { + languageVersion = mainLanguageVersion + } + } + } + else { + // Fallback to JDK8 + java { + sourceCompatibility = JavaVersion.VERSION_1_8 + } + } + // Configure a specific Java Toolchain for compiling and running tests if the 'testToolchain' property is defined + if (project.hasProperty(testToolchain)) { + def testLanguageVersion = JavaLanguageVersion.of(project.property(testToolchain).toString()); + tasks.withType(JavaCompile).matching { it.name.contains("Test") }.configureEach { + javaCompiler = javaToolchains.compilerFor { + languageVersion = testLanguageVersion + } + } + tasks.withType(Test).configureEach{ + javaLauncher = javaToolchains.launcherFor { + languageVersion = testLanguageVersion + } + } + } +} + +plugins.withType(GroovyPlugin) { + // Fallback to JDK8 + if (!project.hasProperty(mainToolchain)) { + compileGroovy { + sourceCompatibility = JavaVersion.VERSION_1_8 + } + } +} + +// Configure the Kotlin compiler if the 'mainToolchain' property is defined +pluginManager.withPlugin("kotlin") { + if (project.hasProperty(mainToolchain)) { + def mainLanguageVersion = JavaLanguageVersion.of(project.property(mainToolchain).toString()); + def compiler = javaToolchains.compilerFor { + languageVersion = mainLanguageVersion + } + // See https://kotlinlang.org/docs/gradle.html#attributes-specific-for-jvm + def javaVersion = mainLanguageVersion.toString() == '8' ? '1.8' : mainLanguageVersion.toString() + compileKotlin { + kotlinOptions { + jvmTarget = javaVersion + jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath + } + } + // Compile the test classes with the same version, 'testToolchain' will override if defined + compileTestKotlin { + kotlinOptions { + jvmTarget = javaVersion + jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath + } + } + } + else { + compileKotlin { + kotlinOptions { + jvmTarget = '1.8' + } + } + } + + if (project.hasProperty(testToolchain)) { + def testLanguageVersion = JavaLanguageVersion.of(project.property(testToolchain).toString()); + def compiler = javaToolchains.compilerFor { + languageVersion = testLanguageVersion + } + // See https://kotlinlang.org/docs/gradle.html#attributes-specific-for-jvm + def javaVersion = testLanguageVersion.toString() == '8' ? '1.8' : testLanguageVersion.toString() + compileTestKotlin { + kotlinOptions { + jvmTarget = javaVersion + jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath + } + } + } + else { + compileTestKotlin { + kotlinOptions { + jvmTarget = '1.8' + } + } + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index be0672db505e..d852c01eb91a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -45,11 +45,11 @@ rootProject.children.each {project -> settings.gradle.projectsLoaded { gradleEnterprise { buildScan { - if (settings.gradle.rootProject.hasProperty('customJavaHome')) { - value("Custom JAVA_HOME", settings.gradle.rootProject.getProperty('customJavaHome')) + if (settings.gradle.rootProject.hasProperty('mainToolchain')) { + value("Main toolchain", 'JDK' + settings.gradle.rootProject.getProperty('mainToolchain')) } - if (settings.gradle.rootProject.hasProperty('customJavaSourceVersion')) { - value("Custom Java Source Version", settings.gradle.rootProject.getProperty('customJavaSourceVersion')) + if (settings.gradle.rootProject.hasProperty('testToolchain')) { + value("Test toolchain", 'JDK' + settings.gradle.rootProject.getProperty('testToolchain')) } File buildDir = settings.gradle.rootProject.getBuildDir() buildDir.mkdirs() diff --git a/spring-beans/spring-beans.gradle b/spring-beans/spring-beans.gradle index 73e9942f8ef6..db894e8b83bc 100644 --- a/spring-beans/spring-beans.gradle +++ b/spring-beans/spring-beans.gradle @@ -23,8 +23,6 @@ sourceSets { } compileGroovy { - sourceCompatibility = 1.8 - targetCompatibility = 1.8 options.compilerArgs += "-Werror" }