Gradle 9 deprecation and optional dependencies

In Gradle 8.x my project produces the following message:

“The ‘optional’ feature was created using the main source set. This behavior has been deprecated. This will fail with an error in Gradle 9.0. The main source set is reserved for production code and should not be used for features.”

I’m using registerFeature as a means to create optional dependency entries in the published pom. The basis for this was taken from a blog post.

java {
  registerFeature('optional') {
    usingSourceSet sourceSets.main
  }
}

And for the dependencies:

dependencies {
  ...
  optionalImplementation "javax.cache:cache-api:${javaxCacheApiVersion}"
  optionalImplementation "org.ow2.asm:asm:${asmVersion}"
  ...
}

The pom will have the following entries:

<dependency>
  <groupId>javax.cache</groupId>
  <artifactId>cache-api</artifactId>
  <version>1.1.1</version>
  <scope>runtime</scope>
  <optional>true</optional>
</dependency>
<dependency>
  <groupId>org.ow2.asm</groupId>
  <artifactId>asm</artifactId>
  <version>[6.0,)</version>
  <scope>runtime</scope>
  <optional>true</optional>
</dependency>

Apparently starting with Gradle 9 this will not work anymore.

So, what’s the correct way to solve this problem?

https://docs.gradle.org/current/userguide/upgrading_version_8.html#changes_8.6

You should take a look at the updated documentation

Here’s how I handle it,This may be illegal, but it achieves the results I want

I created Please revert the deprecation to declare additional feature variants on the `main` source set · Issue #29455 · gradle/gradle · GitHub to revert the deprecation and Allow to declare multiple feature variants on the same non-`main` source set · Issue #29457 · gradle/gradle · GitHub to extend the functionality from main to custom source sets.

But in the meantime, or if the deprecation is not going to be reverted, this should work as expected (it is written in Kotlin DSL but you can translate it to Groovy DSL too):

plugins {
    `java-library`
    `maven-publish`
}

group = "showcase"
version = "0.1.0-SNAPSHOT"

publishing {
    val library by publications.registering(MavenPublication::class) {
        from(components["java"])
    }
}

val optional by sourceSets.creating
java {
    registerFeature("optional") {
        usingSourceSet(optional)
    }
}
val optionalImplementation by configurations.existing
dependencies {
    optionalImplementation("javax.cache:cache-api:$javaxCacheApiVersion")
    optionalImplementation("org.ow2.asm:asm:$asmVersion")
}

val apiElements by configurations.getting
val optionalApiElements by configurations.existing {
    outgoing.artifacts.clear()
    apiElements.artifacts.forEach(outgoing::artifact)
    extendsFrom(apiElements)
}
val runtimeElements by configurations.getting
val optionalRuntimeElements by configurations.existing {
    outgoing.artifacts.clear()
    runtimeElements.artifacts.forEach(outgoing::artifact)
    extendsFrom(runtimeElements)
}
1 Like