This message was deleted.
# community-support
s
This message was deleted.
e
I tried using
compileOnly
in my library, but now when I use the library in one of my projects I get the error:
Copy code
Unable to load class 'org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper'.

This is an unexpected error. Please file a bug containing the idea.log file.
I only get the error above if I have the following in my
settings.gradle.kts
Copy code
buildscript {
  repositories {
    mavenLocal()
  }

  dependencies {
    classpath("my-library")
  }
}
If I take that out, then everything works. However, I want to use a function from my library in the
dependencyResolutionManagement
block to add a repository (I have
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
set). I can add the
buildscript
block above to
build.gradle.kts
and then everything works fine (except I can't use the library to add the repository).
I just tried in another project and it works fine šŸ¤” The only thing that's different about the project that doesn't work is that it uses
kotlin-dsl
m
I think
compileOnly
is the good call. More generally, your lib also shouldn't have
kotlin-stdlib
in its dependencies so you should have
kotlin.stdlib.default.dependency=false
(but that is most likely not really related to your immediate problem)
Copy code
Unable to load class 'org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper'.
Do you have the stacktrace for this? Every code you write that needs the KGP symbols needs to be called from something like
Copy code
plugins.withId("org.jetbrains.kotlin.jvm") { // or ".multiplatform"
  // do stuff here
}
And for classloading to work, you certainly want to isolate such code in separate classes that the JVM doesn't try to load until it has loaded the KGP jar
For an exemple, we're doing this
e
The stacktrace is much longer, but here's the relevant part. I'm thinking it's related to the library using
compileOnly
for the kotlin plugin, but if I add the kotlin plugin as a classpath dependency in the project the error still occurs.
Copy code
* Exception is:
java.lang.NoClassDefFoundError: org/jetbrains/kotlin/gradle/dsl/ExplicitApiMode
        at com.eygraber.gradle.kotlin.KgpKt.configureKgp$default(kgp.kt:17)
        at Build_gradle.<init>(build.gradle.kts:27)
        at Program.execute(Unknown Source)
        at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.eval(Interpreter.kt:532)
        at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.evaluateSecondStageOf(Interpreter.kt:438)
        at Program.execute(Unknown Source)
        at org.gradle.kotlin.dsl.execution.Interpreter$ProgramHost.eval(Interpreter.kt:532)
        at org.gradle.kotlin.dsl.execution.Interpreter.eval(Interpreter.kt:184)
m
You don't control the loading of the KGP, you can only react to it with
plugins.withId("org.jetbrains.kotlin....") {}
Well, if you add it as a runtime dependency, you technically control it but that's going against what another script might want to do
Gradle classloaders are surprising to say the least so depending where you add it, it might not be seen everywhere
e
I tried that, and it still doesn't work. In the library I use
plugins.withType(KotlinBasePluginWrapper::class.java)
before interacting with it, and in the project I tried wrapped the usage of the library in that and it still didn't work. I have 2 plugins that are
compileOnly
in the library; detekt and Kotlin. If I make Kotlin
implementation
then the error changes to not being able to load detekt classes
m
plugins.withType(KotlinBasePluginWrapper::class.java)
Can that even work? That'd mean
KotlinBasePluginWrapper
is already in the classpath...
You might have a different version of the KGP than what you'd expect
What I'd do is remove all buildscript.classpath dependencies from
settings.gradle.kts
and
build.gradle.kts
in your project and load everything from regular (non-buildscript)
buildSrc
dependencies
Using this, dependency and conflict resolution usually work as expected given that all your dependencies are in a single place
e
Looks like the issue is that because I am adding the library in
settings.gradle.kts
buildscript, and because the library has a
compileOnly
dependency on
kotlinGradleDsl
, there is no implementation being used. If I add
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21")
to the
settings.gradle.kts
buildscript then it works, but if I only add it to the
build.gradle.kts
buildscript it doesn't work, even though the
NoClassDefFoundError
is happening in the
build.gradle.kts
.
m
Classloader fun šŸ˜…
e
So to simplify the problem, I have a library that applies
kotlin-dsl
, and a project that has a classpath dependency on that library in
settings.gradle.kts
and applies
kotlin-dsl
in
build.gradle.kts
Unless I include a classpath dependency on
kgp
in the project's
settings.gradle.kts
, I get
NoClassDefFoundError
for code that's called from the library in
build.gradle.kts
m
Do you need the
settings.gradle.kts
part? Usually KGP and others are applied in
build.gradle.kts
e
I have a function in the library that configures a maven repo for github packages, and I need to use it in
dependencyResolutionManagement
because I have
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
set (which only allows repos to be configured in that block in
settings.gradle.kts
)
m
I see...
"Maybe" (with a lot of quotes), the settings classloader is a parent of the build.gradle.kts classloader and therefore doesn't see the KGP because it's loaded in a child classloader
That'd explain why your lib classes cannot see the KGP classes somehow
In which case you'd have to either: • load everything in the settings classloader • or split your lib in 2, one settings part and one build part
Again, this is "just" a wild guess, this stuff is hard
e
The funny thing is that I'm loading it in the
build.gradle.kts
buildscript as well, and everything works fine as long as I don't load it in the
settings.gradle.kts
buildscript
m
That'd be consistent with the "classloader" hierarchy
Ah well maybe not. If it's loaded twice, your
build.gradle.kts
should take precedence
Or maybe not...
Oh well

https://storage.googleapis.com/programming-idioms-pictures/idiom/149/princess-java.pngā–¾

šŸ˜‚ 1
e
Yeah this is a real head scratcher. Thanks for helping!
I'm afraid that some of this has been a wild goose chase, and I've been asking the wrong questions. I originally tried using
compileOnly
for kgp and detekt because of this error:
Copy code
Error resolving plugin [id: 'io.gitlab.arturbosch.detekt', version: '1.21.0']
> The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version, so compatibility cannot be checked.
By adding the kgp dependency as implementation instead of compileOnly the issue is resolved. However I now get a
NoClassDefFoundError
for detekt plugin classes. So the issue is that if detekt is
implementation
I get the error about resolving the plugin, and if it is
compileOnly
I get the
NoClassDefFoundError
. Adding the detekt plugin to the
settings.gradle.kts
buildscript dependencies results in the error about resolving the plugin. And now I realize the problem is that because the library brings kgp and detekt onto the project's classpath, I can't specify the version when applying the kgp and detekt plugins. However, I'm applying them using version catalogs (
alias(libs.plugins.kotlin)
, etc...) which I thought should allow the same version to be specified (https://github.com/gradle/gradle/pull/19015) however I just realized that Gradle doesn't know the version of the plugin on the classpath, which is not supported. So the solution is to use
implementation
for the plugins in the library, and not specify the plugin version in the project šŸ™ˆ
m
Ah nice that it works!