bazelbuild / rules_kotlin

Bazel rules for Kotlin
Apache License 2.0
328 stars 205 forks source link

KSP subplugin conflicts with guava in @com_github_jetbrains_kotlin//lib/kotlin-compiler.jar #1168

Open xinzhengzhang opened 2 months ago

xinzhengzhang commented 2 months ago

Description:

There are some guava classes in Kotlin-compiler, such as com.google .common.graph, if guava is also used in the subplugin of ksp, then because the parent delegation model of java will go to the father, that is, the guava in MemoryBasedClassLoader, which will lead to

Exception: java.lang. LinkageError: loader constraint violation: loader'app 'wants to load interface com.google common.base. Supplier. A different interface with the same name was previously loaded by org.jetbrains.kotlin.preloading.MemoryBasedClassLoader @4bbfb90a. (com.google common.base. Supplier is in unnamed module of loaderorg.jetbrains.kotlin.preloading.MemoryBasedClassLoader @4bbfb90a, parent loader'bootstrap')

The same error occurs with compile ksp in cli mode

Workaround: Essentially, Kotlinc should solve the problem of isolation from the KSP environment, but considering that rules_kotlin builders currently have a relatively complete guava, I filtered out guava in the MemoryBasedClassLoader load condition, but this solution does not look elegant, and I would like to discuss how to deal with it.

diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt
index 18ea6c1..0455481 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt
+++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt
@@ -20,6 +20,7 @@ import io.bazel.kotlin.builder.utils.BazelRunFiles
 import io.bazel.kotlin.builder.utils.resolveVerified
 import io.bazel.kotlin.builder.utils.verified
 import io.bazel.kotlin.builder.utils.verifiedPath
+import org.jetbrains.kotlin.preloading.ClassCondition
 import org.jetbrains.kotlin.preloading.ClassPreloadingUtils
 import org.jetbrains.kotlin.preloading.Preloader
 import java.io.File
@@ -190,7 +191,12 @@ class KotlinToolchain private constructor(
         },
         Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE,
         classLoader,
-        null,
+        // null,
+        object: ClassCondition {
+          override fun accept(className: String): Boolean {
+            return className.startsWith("com.google.common.")
+          }
+        }
       )
     }.onFailure {
       throw RuntimeException("$javaHome, $baseJars", it)