vanniktech / gradle-maven-publish-plugin

A Gradle plugin that publishes your Android and Kotlin libraries, including sources and javadoc, to Maven Central or any other Nexus instance.
https://vanniktech.github.io/gradle-maven-publish-plugin
Apache License 2.0
1.29k stars 119 forks source link

ClassNotFound error when applying the plugin without kotlin #846

Closed sureshg closed 2 days ago

sureshg commented 1 week ago

I have a small multi module project, where the root build.gradle.kts has the following plugin configuration

plugins {
  idea
  wrapper
  alias(libs.plugins.semver)
  alias(libs.plugins.benmanes)
  alias(libs.plugins.spotless)
  alias(libs.plugins.vanniktech.publish) apply false
}

The root project doesn't have any publishable artifact, but adding the vanniktech plugin just to avoid some weird class loading issue. One of the modules is a project with kotlin-dsl plugin applied

plugins/build.gradle.kts

plugins {
  idea
  `kotlin-dsl`
  embeddedKotlin("plugin.serialization")
  alias(libs.plugins.jte)
  alias(libs.plugins.benmanes)
  alias(libs.plugins.spotless)
  alias(libs.plugins.semver)
  alias(libs.plugins.vanniktech.publish)
}

When I run the build with this configuration, the plugin throws following error.

* What went wrong:
org/jetbrains/kotlin/gradle/plugin/KotlinBasePlugin
> org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin

* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

* Exception is:
java.lang.NoClassDefFoundError: org/jetbrains/kotlin/gradle/plugin/KotlinBasePlugin
        at com.vanniktech.maven.publish.ProjectExtensionsKt.isAtLeastKotlinVersion(ProjectExtensions.kt:60)
        at com.vanniktech.maven.publish.MavenPublishBasePlugin.checkMinimumVersions$lambda$4$lambda$2(MavenPublishBasePlugin.kt:28)
        at com.vanniktech.maven.publish.MavenPublishBasePlugin.checkMinimumVersions$lambda$4$lambda$3(MavenPublishBasePlugin.kt:27)
        at org.gradle.internal.code.DefaultUserCodeApplicationContext$CurrentApplication$1.execute(DefaultUserCodeApplicationContext.java:124)
        at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction$1.run(DefaultCollectionCallbackActionDecorator.java:110)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
        at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction.execute(DefaultCollectionCallbackActionDecorator.java:107)
        at org.gradle.api.internal.collections.CollectionFilter$1.execute(CollectionFilter.java:62)
        at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:161)
        at org.gradle.api.internal.plugins.DefaultPluginContainer$2.execute(DefaultPluginContainer.java:163)
        at org.gradle.api.internal.plugins.DefaultPluginContainer$2.execute(DefaultPluginContainer.java:154)

IIUC, correctly, kotlin plugin is not a requirement for this plugin and should gracefully fall back to no-op.

gabrielittner commented 1 week ago

Could you try adding kotlin-dsl with apply false to the root project? isAtLeastKotlinVersion will only be called if either the org.jetbrains.kotlin.jvm or org.jetbrains.kotlin.multiplatform is applied to the project. The kotlin-dsl plugon will apply kotlin jvm so that the check is executed is intentional. My theory is that because the publish plugin is on the root project classloader but kotlin-dsl only on the plugin project that it can't see the Kotlin plugin properly.

sureshg commented 1 week ago

Could you try adding kotlin-dsl with apply false to the root project?

Still have the same error.

My theory is that because the publish plugin is on the root project classloader but kotlin-dsl only on the plugin project that it can't see the Kotlin plugin properly.

Yeah, somehow worked around this by doing something like below. Not sure whether it's a good solution or not.

 # build-logic plugin
  implementation("${libs.build.kotlin.dsl.get().module}:${expectedKotlinDslPluginsVersion}")

// Plugin Project
plugins {
  // Just apply with `kotlin-dsl` id.
  id("org.gradle.kotlin.kotlin-dsl")
  embeddedKotlin("plugin.serialization")
  com.github.`ben-manes`.versions
  com.diffplug.spotless
  gg.jte.gradle
  plugin.publishing
}
gabrielittner commented 2 days ago

That workaround is perfectly fine. The altnernative would be to add a dependency on the publish plugin in build logic. Both achieve that the Kotlin plugin and the publish plugin are part of the same classloader and can see each other.

sureshg commented 6 hours ago

@gabrielittner thanks..Does it make sense to use java reflection to avoid these class loader issues for getting the plugin version?..something like

plugins.withId("org.jetbrains.kotlin.multiplatform") {
   val pluginVersion = javaClass.getMethod("getPluginVersion").invoke(this).toString()
}