1

I am migrating a Maven library project to Gradle. The original project also has optional dependencies. I use the java-library plugin but moving the formerly optional dependencies to implementation results in runtime dependencies instead of compile. So I tried the gradle feature variants which results in the right dependencies in the pom.xml. But doing so results is failing test compile as the dependencies of the feature variant are missing on the test compile classpath!

Here is my current setup in build.gradle:

apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'maven-publish'

sourceCompatibility = 1.8

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

dependencies {
  api 'my.compile:dep-a:1.0.0'
  implementation 'my.runtime:dep-i:1.0.0'
  oSupportApi 'my.optional:dep-o:1.0.0'
}

Let's assume there is a class O available from my.optional:dep-o. If I import O in any class in src/main/java it works perfectly. Also the dependencies are exported right to Maven (using gradle generatePomFileForMavenJavaPublication, see the dependencies from the generated pom.xml below). But any test in src/test/java using class O will not compile (import my.optional.O; creates error: package my.optional does not exist)

<dependencies>
    <dependency>
      <groupId>my.compile</groupId>
      <artifactId>dep-a</artifactId>
      <version>1.0.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>my.rintime</groupId>
      <artifactId>dep-r</artifactId>
      <version>1.0.0</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>my.optional</groupId>
      <artifactId>dep-0</artifactId>
      <version>1.0.0</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
</dependencies>

How to solve this? I know I could have used the nebula.optional-base plugin instead of the buildin Gradle feature variant but I would prefer the new gradle builtin support for optional dependencies instead.

PS: I use Java 8 and Gradle 5.6.2

Arne Burmeister
  • 20,046
  • 8
  • 53
  • 94

2 Answers2

3

This looks like a bug when the feature source set uses the main source set. Can you report on https://github.com/gradle/gradle/issues?

In the meantime, this should fix it:

configurations {
    testCompileClasspath.extendsFrom(oSupportApi)
    testRuntimeClasspath.extendsFrom(oSupportApi)
    testRuntimeClasspath.extendsFrom(oSupportImplementation)
}
melix
  • 1,510
  • 7
  • 6
1

Really weird, I agree with @melix this seems to be a Gradle bug.

The following will fix it but should not be needed, imho:

dependencies {
  api 'my.compile:dep-a:1.0.0'
  implementation 'my.runtime:dep-i:1.0.0'
  oSupportApi 'my.optional:dep-o:1.0.0'
  testImplementation(project(":${project.name}")) {
    capabilities {
      requireCapability("${project.group}:${project.name}-o-support")
    }
  }
}

For this simplified setup with only one feature dependency could be replaced by testImplementation 'my.optional:dep-o:1.0.0' but for a general larger dependency list this approch avoids repetition of the dependencies as the extendsFrom solution of @melix.

Arne Burmeister
  • 20,046
  • 8
  • 53
  • 94