Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requiring toolchains unconditionally (e.g., in JavaCompile) introduced unexpected incompatible changes #24055

Closed
TheMrMilchmann opened this issue Feb 27, 2023 · 3 comments
Labels
closed:duplicate Duplicated or superseeded by another issue

Comments

@TheMrMilchmann
Copy link
Contributor

Expected Behavior

On Gradle 7.+, setting a tool for a default Java task (e.g., javaCompiler for JavaCompile) to a provider would fall back to the project-wide toolchain (if available) or the running JVM otherwise if the provider has no value.

Current Behavior

Doing the same on Gradle 8.0 and 8.0.1 fails because the toolchain is now required unconditionally. This is problematic because there is no proper replacement available and the behavior was not previously explicitly deprecated.

Context

I'm facing this issue when using Gradle properties to configure the toolchain for a specific task. Specifically, I'm using a provider returned by ProviderFactory#gradleProperty(String) to derive the tool roughly as follows:

val java = extensions.getByType<JavaPluginExtension>()
val javaToolchains = extensions.getByType<JavaToolchainService>()

tasks.withType<JavaCompile>().configureEach() {

    javaCompiler.set(providers.gradleProperty("$name.toolchain").map {
        javaToolchains.compilerFor {
            languageVersion.set(JavaLanguageVersion.of(it))
        }
    })

}

Note that this wouldn't be too much of a problem if a setter method on Property that would take a provider but fallback to the convention if the provider has no value existed. (Related to the discussion in #14768)

This is also somewhat related to #23990.

Steps to Reproduce

I'm not going to provide a full MCVE this time around, because the issue is sufficiently outlined above. To reproduce the problem, create a project with the following contents in a build.gradle.kts file and attempt to run the compileJava task. (You might need to also add a dummy class to the sources to avoid the task getting skipped.) On Gradle 7.+, this would cause the task to use the project-wide toolchain. However, due to the described changes, this fails on 8.0 and 8.0.1.

plugins {
    `java-library`
}

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(11))
    }
}

tasks.withType<JavaCompile>().configureEach {
    javaCompiler.set(provider { null })
}
@alllex
Copy link
Member

alllex commented Feb 27, 2023

It seems, until #14768 is addressed in some way, if a provider is passed to the .set() method of a property it acts as a single source of the value for this property (convention is ignored). If the property in question is not @Optional it means the provider itself must be responsible for handling the missing-value case.

For the use case described in the issue, there are two main options: explicitly fallback to the Build JVM toolchain or to the project-wide toolchain. This could be done the following way:

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(11))
    }
}

val currentJvmToolchainCompiler: Provider<JavaCompiler> = javaToolchains.compilerFor {}
val projectToolchainCompiler: Provider<JavaCompiler> = provider { java.toolchain }.flatMap { javaToolchains.compilerFor(it) }

tasks.withType<JavaCompile>().configureEach {
    javaCompiler.set(provider<JavaCompiler> { null }.orElse(projectToolchainCompiler))
}

@Vampire
Copy link
Contributor

Vampire commented Feb 27, 2023

I think the main complaint here, is that something that worked in Gradle 7.6 without deprecation warning is failing the build now with Gradle 8, contrary to how it is usually handled in Gradle and documented at https://docs.gradle.org/current/userguide/feature_lifecycle.html

@eskatos eskatos added closed:duplicate Duplicated or superseeded by another issue and removed a:regression This used to work to-triage labels Mar 1, 2023
@eskatos
Copy link
Member

eskatos commented Mar 1, 2023

Thank you for your interest in Gradle!

This issue will be closed as a duplicate of

Please add your use case and 👍 to that issue.


While we recognize this is an unexpected breaking change the alternative until the issue above is fixed has its own issues. We will keep that change as is since 8.0 is a major release.

@eskatos eskatos closed this as not planned Won't fix, can't repro, duplicate, stale Mar 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed:duplicate Duplicated or superseeded by another issue
Projects
None yet
Development

No branches or pull requests

4 participants