Skip to content

Commit

Permalink
Require Gradle 6.8+
Browse files Browse the repository at this point in the history
Gradle 6.7 introduced toolchains, but Gradle 6.8
updated Kotlin to 1.4, which will make it possible
to build with Gradle 7.x while still being backwards
compatible down to Gradle 6.8, due to KT-27362.
  • Loading branch information
tbroyer committed Oct 2, 2022
1 parent e3fe8d7 commit 7410cc0
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/gradle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
gradle: [ '7.5', '7.4.2', '7.3.3', '7.2', '7.1.1', '7.0.2', '6.8.3', '6.7.1', '6.6.1', '6.5.1', '6.4.1', '6.3', '6.2.2', '6.1.1', '6.0.1', '5.6.4', '5.5.1', '5.4.1', '5.3.1', '5.2.1' ]
gradle: [ '7.5', '7.4.2', '7.3.3', '7.2', '7.1.1', '7.0.2', '6.8.3' ]
steps:
- uses: actions/checkout@v2

Expand Down
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This plugin configures `JavaCompile` tasks to use the [Error Prone compiler].

## Requirements

This plugin requires using at least Gradle 5.2.
This plugin requires using at least Gradle 6.8.

While JDK 8 is supported, it is recommended to use at least a JDK 9 compiler.
See [note below](#jdk-8-support) about JDK 8 support.
Expand All @@ -19,8 +19,6 @@ plugins {
}
```

_Note: snippets in this guide use features from the latest Gradle version, so beware if copy/pasting._

This plugin creates a configuration named `errorprone`,
and configures the `<sourceSet>AnnotationProcessor` configuration for each source set to extend it.
This allows configuring Error Prone dependencies from a single place.
Expand Down Expand Up @@ -61,16 +59,20 @@ tasks.withType<JavaCompile>().configureEach {

and can also be disabled altogether:
```gradle
tasks.named("compileTestJava").configure {
options.errorprone.enabled = false
tasks {
compileTestJava {
options.errorprone.enabled = false
}
}
```
<details>
<summary>with Kotlin DSL</summary>

```kotlin
tasks.named<JavaCompile>("compileTestJava") {
options.errorprone.isEnabled.set(false)
tasks {
compileTestJava {
options.errorprone.isEnabled.set(false)
}
}
```

Expand Down Expand Up @@ -134,13 +136,13 @@ and the plugin will configure the `JavaCompile` tasks to [use a forking compiler
and will override the compiler by prepending the dependencies to the bootstrap classpath
(using a `-Xbootclasspath/p:` [JVM argument][BaseForkOptions.getJvmArgs]).

Starting with Gradle 6.7, you can [configure `JavaCompile` tasks][gradle-toolchains] to use a specific JDK compiler,
You can [configure `JavaCompile` tasks][gradle-toolchains] to use a specific JDK compiler,
independently of the JDK used to run Gradle itself.
The plugin will use the toolchain version, if any is specified, to configure the task.
This allows you to enforce compilation with JDK 8 (properly configured for Error Prone!) while running Gradle with e.g. JDK 11,
or the reverse: enforce compilation with JDK 11 while running Gradle with JDK 8.

Alternatively, or for previous versions of Gradle, you can [configure `JavaCompile` tasks][ForkOptions.setJavaHome] to use such a JDK while still using JDK 8 for running Gradle:
Alternatively, you can [configure `JavaCompile` tasks][ForkOptions.setJavaHome] to use such a JDK while still using JDK 8 for running Gradle:
```gradle
tasks.withType(JavaCompile).configureEach {
options.fork(javaHome: project.getProperty("jdk11home"))
Expand Down Expand Up @@ -191,7 +193,7 @@ someTask.configure {

(if you're using `forkOptions.executable`, then use `-J-Xbootclasspath/p:` instead.)

[gradle-toolchains]: https://docs.gradle.org/6.7/userguide/toolchains.html
[gradle-toolchains]: https://docs.gradle.org/current/userguide/toolchains.html
[CompileOptions.fork]: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html#org.gradle.api.tasks.compile.CompileOptions:fork
[BaseForkOptions.getJvmArgs]: https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/compile/BaseForkOptions.html#getJvmArgs--
[ForkOptions.setJavaHome]: https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/compile/ForkOptions.html#setJavaHome-java.io.File-
Expand Down Expand Up @@ -236,7 +238,7 @@ tasks.withType(JavaCompile).configureEach {
option("NullAway:AnnotatedPackages", "net.ltgt")
}
}
tasks.named("compileJava").configure {
tasks.compileJava {
// The check defaults to a warning, bump it up to an error for the main sources
options.errorprone.error("NullAway")
}
Expand All @@ -250,7 +252,7 @@ tasks.withType<JavaCompile>().configureEach {
option("NullAway:AnnotatedPackages", "net.ltgt")
}
}
tasks.named("compileJava", JavaCompile::class) {
tasks.compileJava {
// The check defaults to a warning, bump it up to an error for the main sources
options.errorprone.error("NullAway")
}
Expand Down
69 changes: 29 additions & 40 deletions src/main/kotlin/net/ltgt/gradle/errorprone/ErrorPronePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ Add a dependency to com.google.errorprone:javac with the appropriate version cor
}
"""

private val HAS_TOOLCHAINS = GradleVersion.current().baseVersion >= GradleVersion.version("6.7")

internal const val TOO_OLD_TOOLCHAIN_ERROR_MESSAGE = "Must not enable ErrorProne when compiling with JDK < 8"

internal val JVM_ARGS_STRONG_ENCAPSULATION = listOf(
Expand All @@ -71,8 +69,8 @@ Add a dependency to com.google.errorprone:javac with the appropriate version cor
}

override fun apply(project: Project) {
if (GradleVersion.current() < GradleVersion.version("5.2")) {
throw UnsupportedOperationException("$PLUGIN_ID requires at least Gradle 5.2")
if (GradleVersion.current() < GradleVersion.version("6.8")) {
throw UnsupportedOperationException("$PLUGIN_ID requires at least Gradle 6.8")
}

val errorproneConfiguration = project.configurations.create(CONFIGURATION_NAME) {
Expand Down Expand Up @@ -111,48 +109,42 @@ Add a dependency to com.google.errorprone:javac with the appropriate version cor
.compilerArgumentProviders
.add(ErrorProneCompilerArgumentProvider(errorproneOptions))

if (HAS_TOOLCHAINS || JavaVersion.current().run { isJava8 || isJava16Compatible }) {
inputs.files(
providers.provider {
when {
!errorproneOptions.isEnabled.getOrElse(false) -> emptyList()
HAS_TOOLCHAINS && javaCompiler.isPresent ->
when (javaCompiler.get().metadata.languageVersion.asInt()) {
8 -> javacConfiguration
else -> emptyList()
}
JavaVersion.current().isJava8 && !options.isCommandLine -> javacConfiguration
else -> emptyList()
}
}
).withPropertyName(JAVAC_CONFIGURATION_NAME).withNormalizer(ClasspathNormalizer::class)
doFirst("configure errorprone in bootclasspath") {
inputs.files(
providers.provider {
when {
!errorproneOptions.isEnabled.getOrElse(false) -> return@doFirst
HAS_TOOLCHAINS && javaCompiler.isPresent -> {
val targetVersion = javaCompiler.get().metadata.languageVersion.asInt()
when {
targetVersion < 8 -> throw UnsupportedOperationException(TOO_OLD_TOOLCHAIN_ERROR_MESSAGE)
targetVersion == 8 -> configureErrorProneJavac()
targetVersion >= 16 -> configureForJava16plus()
!errorproneOptions.isEnabled.getOrElse(false) -> emptyList()
javaCompiler.isPresent ->
when (javaCompiler.get().metadata.languageVersion.asInt()) {
8 -> javacConfiguration
else -> emptyList()
}
JavaVersion.current().isJava8 && !options.isCommandLine -> javacConfiguration
else -> emptyList()
}
}
).withPropertyName(JAVAC_CONFIGURATION_NAME).withNormalizer(ClasspathNormalizer::class)
doFirst("configure errorprone in bootclasspath") {
when {
!errorproneOptions.isEnabled.getOrElse(false) -> return@doFirst
javaCompiler.isPresent -> {
val targetVersion = javaCompiler.get().metadata.languageVersion.asInt()
when {
targetVersion < 8 -> throw UnsupportedOperationException(TOO_OLD_TOOLCHAIN_ERROR_MESSAGE)
targetVersion == 8 -> configureErrorProneJavac()
targetVersion >= 16 -> configureForJava16plus()
}
JavaVersion.current().isJava8 && !options.isCommandLine ->
configureErrorProneJavac()
JavaVersion.current().isJava16Compatible && !options.isCommandLine ->
configureForJava16plus()
}
JavaVersion.current().isJava8 && !options.isCommandLine ->
configureErrorProneJavac()
JavaVersion.current() >= JavaVersion.VERSION_16 && !options.isCommandLine ->
configureForJava16plus()
}
}
}

val enableErrorProne: JavaCompile.(Boolean) -> Unit = { testOnly ->
options.errorprone {
if (HAS_TOOLCHAINS) {
isEnabled.convention(javaCompiler.map { it.metadata.languageVersion.asInt() >= 8 }.orElse(true))
} else {
isEnabled.convention(true)
}
isEnabled.convention(javaCompiler.map { it.metadata.languageVersion.asInt() >= 8 }.orElse(true))
isCompilingTestOnlyCode.convention(testOnly)
}
}
Expand Down Expand Up @@ -192,7 +184,7 @@ Add a dependency to com.google.errorprone:javac with the appropriate version cor
options.isFork = true
// See org.gradle.api.internal.tasks.compile.AbstractJavaCompileSpecFactory#isCurrentVmOurToolchain
// reset forkOptions in case they were configured, but only when not using a toolchain
if (!HAS_TOOLCHAINS || !javaCompiler.isPresent) {
if (!javaCompiler.isPresent) {
options.forkOptions = ForkOptions()
}
}
Expand Down Expand Up @@ -229,8 +221,5 @@ internal class ErrorProneCompilerArgumentProvider(
internal val TEST_SOURCE_SET_NAME_REGEX =
"""^(t|.*T)est(\p{javaUpperCase}.*)?$""".toRegex()

internal val JavaVersion.isJava16Compatible: Boolean
get() = this < JavaVersion.VERSION_HIGHER && this >= JavaVersion.toVersion(16)

private val CompileOptions.isCommandLine
get() = isFork && (forkOptions.javaHome != null || forkOptions.executable != null)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.google.common.truth.Truth.assertThat
import com.google.common.truth.TruthJUnit.assume
import org.gradle.api.JavaVersion
import org.gradle.testkit.runner.TaskOutcome
import org.gradle.util.GradleVersion
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.io.File
Expand All @@ -15,7 +14,6 @@ class AndroidIntegrationTest : AbstractPluginIntegrationTest() {

@BeforeEach
fun setupAndroid() {
assume().that(GradleVersion.version(testGradleVersion)).isAtLeast(GradleVersion.version("6.5"))
assume().withMessage("isJava16Compatible").that(JavaVersion.current()).isLessThan(JavaVersion.VERSION_16)
assertThat(androidSdkHome).isNotEmpty()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ErrorPronePluginIntegrationTest : AbstractPluginIntegrationTest() {
}
""".trimIndent()
)
if (JavaVersion.current().isJava16Compatible && GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")) {
if (JavaVersion.current() >= JavaVersion.VERSION_16 && GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")) {
// https://melix.github.io/blog/2021/03/gradle-java16.html
buildFile.appendText(
"""
Expand Down Expand Up @@ -168,9 +168,8 @@ class ErrorPronePluginIntegrationTest : AbstractPluginIntegrationTest() {

@Test
fun `is configuration-cache friendly`() {
assume().that(GradleVersion.version(testGradleVersion)).isAtLeast(GradleVersion.version("6.6"))
assume().that(
JavaVersion.current().isJava16Compatible &&
JavaVersion.current() >= JavaVersion.VERSION_16 &&
GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")
).isFalse()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class GroovyDslIntegrationTest {
@BeforeEach
fun setupProject() {
assume().that(
JavaVersion.current().isJava16Compatible &&
JavaVersion.current() >= JavaVersion.VERSION_16 &&
GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")
).isFalse()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {
compileJava.options.forkOptions.jvmArgs!!.add("-XshowSettings")
""".trimIndent()
)
if (JavaVersion.current().isJava16Compatible && GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")) {
if (JavaVersion.current() >= JavaVersion.VERSION_16 && GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")) {
// https://melix.github.io/blog/2021/03/gradle-java16.html
buildFile.appendText(
"""
Expand Down Expand Up @@ -150,7 +150,7 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {

@Test
fun `does not configure forking if Error Prone is disabled`() {
assume().withMessage("isJava8Or16plus").that(JavaVersion.current().run { isJava8 || isJava16Compatible }).isTrue()
assume().withMessage("isJava8Or16plus").that(JavaVersion.current().run { isJava8 || this >= JavaVersion.VERSION_16 }).isTrue()

// given
buildFile.appendText(
Expand Down Expand Up @@ -348,13 +348,7 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {
"""
buildCache {
local${
if (GradleVersion.version(testGradleVersion) < GradleVersion.version("6.0")) {
"(DirectoryBuildCache::class.java)"
} else {
""
}
} {
local {
directory = file("build-cache")
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package net.ltgt.gradle.errorprone

import com.google.common.truth.Truth.assertThat
import com.google.common.truth.TruthJUnit.assume
import org.gradle.api.JavaVersion
import org.gradle.testkit.runner.TaskOutcome
import org.gradle.util.GradleVersion
Expand All @@ -11,9 +10,6 @@ class ManualConfigurationIntegrationTest : AbstractPluginIntegrationTest() {

@Test
fun `in non-java project with applied plugin`() {
// jvm-ecosystem plugin has been added in Gradle 6.7
assume().that(GradleVersion.version(testGradleVersion).baseVersion).isAtLeast(GradleVersion.version("6.7"))

// given
buildFile.appendText(
"""
Expand Down Expand Up @@ -46,7 +42,7 @@ class ManualConfigurationIntegrationTest : AbstractPluginIntegrationTest() {
}
""".trimIndent()
)
if (JavaVersion.current().isJava16Compatible && GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")) {
if (JavaVersion.current() >= JavaVersion.VERSION_16 && GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")) {
// https://melix.github.io/blog/2021/03/gradle-java16.html
buildFile.appendText(
"""
Expand Down Expand Up @@ -100,7 +96,7 @@ class ManualConfigurationIntegrationTest : AbstractPluginIntegrationTest() {
}
""".trimIndent()
)
if (JavaVersion.current().isJava16Compatible && GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")) {
if (JavaVersion.current() >= JavaVersion.VERSION_16 && GradleVersion.version(testGradleVersion) < GradleVersion.version("7.0")) {
// https://melix.github.io/blog/2021/03/gradle-java16.html
buildFile.appendText(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ class ToolchainsIntegrationTest : AbstractPluginIntegrationTest() {

@BeforeEach
fun setup() {
assume().that(GradleVersion.version(testGradleVersion).baseVersion).isAtLeast(GradleVersion.version("6.7"))

testProjectDir.resolve("gradle.properties").appendText(
"""
org.gradle.java.installations.auto-download=false
Expand Down Expand Up @@ -100,12 +98,7 @@ class ToolchainsIntegrationTest : AbstractPluginIntegrationTest() {
override fun getMetadata(): JavaInstallationMetadata = object : JavaInstallationMetadata {
override fun getLanguageVersion(): JavaLanguageVersion = JavaLanguageVersion.of(7)
override fun getInstallationPath(): Directory = TODO()
${
if (GradleVersion.version(testGradleVersion).baseVersion >= GradleVersion.version("6.8")) {
"override fun getVendor(): String = TODO()"
} else {
""
}}
override fun getVendor(): String = TODO()
${
if (GradleVersion.version(testGradleVersion).baseVersion >= GradleVersion.version("7.1")) {
"""override fun getJavaRuntimeVersion(): String = TODO()
Expand Down

0 comments on commit 7410cc0

Please sign in to comment.