Tuning gradle variant compatibility
A real-life case how to force gradle accepting dependency with higer java version requirement.
My animalsniffer gradle plugin targets java 8 (keeps minimum compatiblity):
java {
sourceCompatibility = 1.8
}
Now, in order to add android support, I want to add an optional dependency for android plugin:
dependencies {
compileOnly 'com.android.tools.build:gradle:8.4.0'
}
But, this will not work:
> Could not resolve all files for configuration ':compileClasspath'.
> Could not resolve com.android.tools.build:gradle:8.4.0.
Required by:
project :
> No matching variant of com.android.tools.build:gradle:8.4.0 was found. The consumer was configured to find a library for use during compile-time, compatible with Java 8, preferably not packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '8.6' but:
- Variant 'apiElements' capability com.android.tools.build:gradle:8.4.0 declares a library for use during compile-time, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally:
- Incompatible because this component declares a component, compatible with Java 11 and the consumer needed a component, compatible with Java 8
- Other compatible attribute:
- Doesn't say anything about org.gradle.plugin.api-version (required '8.6')
- Variant 'javadocElements' capability com.android.tools.build:gradle:8.4.0 declares a component for use during runtime, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a library
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
- Doesn't say anything about its target Java version (required compatibility with Java 8)
- Doesn't say anything about its elements (required them preferably not packaged as a jar)
- Doesn't say anything about org.gradle.plugin.api-version (required '8.6')
- Variant 'runtimeElements' capability com.android.tools.build:gradle:8.4.0 declares a library for use during runtime, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally:
- Incompatible because this component declares a component, compatible with Java 11 and the consumer needed a component, compatible with Java 8
- Other compatible attribute:
- Doesn't say anything about org.gradle.plugin.api-version (required '8.6')
- Variant 'sourcesElements' capability com.android.tools.build:gradle:8.4.0 declares a component for use during runtime, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a library
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
- Doesn't say anything about its target Java version (required compatibility with Java 8)
- Doesn't say anything about its elements (required them preferably not packaged as a jar)
- Doesn't say anything about org.gradle.plugin.api-version (required '8.6')
The main problem:
Incompatible because this component declares a component, compatible with Java 11 and the consumer needed a component, compatible with Java 8
No matter what JDK I actually use for this build (17), gradle complains that dependency is not compatible with declared targetCompatibility\=1.8 (not a mistake, by default targetCompatibility == sourceCompatibility)
But, I assume this dependency to be an optional: android project would use java 11 (17) in any case, but my plugin should also work for pure java projects under java 8.
To workaround this moment, I have to manually declare (override) target jvm attribute for configuration (in build.gradle):
import org.gradle.api.attributes.java.TargetJvmVersion
configurations.compileClasspath.attributes
.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 11)
And now java 8 target does not cause problem anymore.
Helpful links: