# Tuning gradle variant compatibility

A real-life case how to force gradle accepting dependency with higer java version requirement.

[My animalsniffer gradle plugin](https://github.com/xvik/gradle-animalsniffer-plugin) targets java 8 (keeps minimum compatiblity):

```java
java {
    sourceCompatibility = 1.8
}
```

Now, in order to add android support, I want to add an optional dependency for android plugin:

```java
dependencies {
    compileOnly 'com.android.tools.build:gradle:8.4.0'
}
```

But, this will not work:

```plaintext
> 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):

```java
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:

1. [Gradle attributes doc](https://docs.gradle.org/current/userguide/variant_attributes.html)
    
2. [Attributes definition example](https://docs.gradle.org/current/userguide/variant_aware_resolution.html#2_create_a_custom_outgoing_configuration)
