2

I'm migrating an older Android library from jcenter to mavenCentral in light of their deprecation. All of the actual library modules are written in Java, but several of them have tests written in Kotlin.

Until upgrading (to AS 4.1.3, Gradle 6.8.3), the generated POM(s) never included a compilation dependency on the kotlin-stdlib. Now it appears that applying the kotlin-android plugin causes the generated POM to add it, even though the dependency is included as testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.31".

  <dependencies>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib</artifactId>
      <version>1.4.31</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

The question: Was the previously-generated POM wrong in that it should have included kotlin as a compilation dependency, even though it's only used for testing?

Or, do I have to do something special to exclude that "dependency" in this specific case? If so, how could I exclude it if generating the POM when defining the publication like:

afterEvaluate {
    publishing {
        publications {
            release(MavenPublication) {
                from components.release
                ....

                pom {
                    name = ...
                    licenses { }
                    developers { }
                    scm { }
                }
            }
        }
    }
}

Or, is that not really a good option and I should just rewrite the tests in Java?

It's worth noting that removing the kotlin-android plugin also removes it as a compilation dependency from the POM(s). It seems to have no effect on generating the AAR; it just prevents the tests from running.

Cruceo
  • 6,763
  • 2
  • 31
  • 52

2 Answers2

7

Since Kotlin 1.4, the various Kotlin Gradle plugins automatically add a dependency on kotlin-std. See Dependency on the standard library.

You can disable it by adding to gradle.properties:

kotlin.stdlib.default.dependency=false
aSemy
  • 5,485
  • 2
  • 25
  • 51
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
0

Going to "answer" my own questions and hope someone corrects me if anything is wrong.

Was the previously-generated POM wrong in that it should have included kotlin as a compilation dependency, even though it's only used for testing?

No, the kotlin-stdlib should not be included in the POM of a release publication for a java/android library that has no kotlin code or kotlin-based dependencies.

I'm making that assertion as I have compiled a java-only app against a version of this library where the kotlin-stdlib compilation condition was removed from the POM, and everything behaved as expected (in that it worked).

If so, how could I exclude it if generating the POM when defining the publication

After defining your POM, you can use pom.withXml from the MavenPom plugin to remove the dependency nodes you want to exclude from the generated POM. e.g.

pom {
    licenses { ... }
    developers { ... }
    scm { ... }
}

pom.withXml {
    asNode()
        .dependencies
        .dependency
        .findAll { it.artifactId.text() == "kotlin-stdlib" }
        .collect { it.parent().remove(it) }
}

Edit: This does not remove the dependencies from the generated module.json, so this now seems even more wrong than it felt before.

Instead, you can check the Gradle Start Parameters to determine which variant is being targeted by the current Task Requests, and only apply the plugin if the variant should actually include it:

def kolinEnabledVariant = getGradle()
        .getStartParameter()
        .getTaskRequests()
        .toString()
        .contains("Debug")

if (kolinEnabledVariant) {
    apply plugin: 'kotlin-android'
}

Commenters on a related answer note that the variant name should start with a capital letter.

Or, is that not really a good option and I should just rewrite the tests in Java?

That's giving up.

Cruceo
  • 6,763
  • 2
  • 31
  • 52