TabooLib / taboolib

Powerful framework for creating multi-platform Minecraft plugin
https://tabooproject.org
MIT License
307 stars 101 forks source link

无法加载包含kotlin或kotlinx的第三方依赖 #406

Closed FALLANGELZOU closed 1 month ago

FALLANGELZOU commented 9 months ago

若添加的第三方依赖,依赖于kotlin或kotlinx,则插件无法正常运行。

   taboo("org.jetbrains.kotlin:kotlin-stdlib:1.8.22") { isTransitive = false }
   taboo("org.jetbrains.kotlin:kotlin-reflect:1.7.22") { isTransitive = false }
   taboo("org.ktorm:ktorm-core:3.6.0") {
        exclude("org.jetbrains.kotlin")
    }

依赖ktorm需要kotlin-reflect和kotlin-stdlib作为依赖。根据文档所有kotlin与kotlinx的依赖必须重定向并采用特殊逻辑。 使用上述依赖打包方式并进行重命名,插件在运行期无法正常工作。并且exclude指令在taboo指令下似乎无法正常工作。

Bkm016 commented 9 months ago

reflect 无法支持 taboolib 的重定向操作,打包kt模块需要关闭 taboolib 的 kotlin 重定向功能。

taboolib { version { skipKotlinRelocate = true } }
Bkm016 commented 9 months ago

若打包 kotlin 环境,还需跳过 taboolib 的 kotlin 环境加载

taboolib { version { skipKotlin = true } }
FALLANGELZOU commented 9 months ago

若打包 kotlin 环境,还需跳过 taboolib 的 kotlin 环境加载

taboolib { version { skipKotlin = true } }

没太理解,当我关闭taboolib的kotlin重定向功能后,插件直接无法加载,显示org.bukkit.plugin.InvalidPluginException: java.lang.NoClassDefFoundError: io/github/username/project/taboolib/common/platform/Plugin,这意思是,kotlin相关的库不重定向就无法使用吗。 当前我的写法如下:

import io.izzel.taboolib.gradle.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    java
    id("io.izzel.taboolib") version "2.0.2"
    id("org.jetbrains.kotlin.jvm") version "1.8.22"
}

taboolib {
    env {
        // 安装模块

        install(UNIVERSAL, BUKKIT)
        install(BUKKIT_UTIL, BUKKIT_ALL)
        install(NMS_UTIL, UI)
        install(DATABASE)
        install(CONFIGURATION)
        install(CHAT)
    }
    version {
        taboolib = "6.1.0"
        skipKotlinRelocate = true
        skipKotlin = true   
    }
    relocate("org.ktorm", "com.angel.lib.ktorm")

}

repositories {
    mavenCentral()
}

dependencies {
    compileOnly("ink.ptms.core:v12004:12004:mapped")
    compileOnly("ink.ptms.core:v12004:v12004:universal")
//    compileOnly(kotlin("stdlib"))
    compileOnly(fileTree("libs"))
    taboo("org.jetbrains.kotlin:kotlin-stdlib:1.8.22") { isTransitive=true }
    taboo("org.jetbrains.kotlin:kotlin-reflect:1.7.22") { isTransitive=true }
    taboo("org.ktorm:ktorm-core:3.6.0") {
        exclude("org.jetbrains.kotlin") 
    }

}

tasks.withType<JavaCompile> {
    options.encoding = "UTF-8"
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        jvmTarget = "1.8"
        freeCompilerArgs = listOf("-Xjvm-default=all")
    }
}

// 编译配置
java {
    withSourcesJar()
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

tasks.register<Copy>("copy2plugin") {
    group = "build"

    dependsOn("build")

    from(layout.buildDirectory.dir("libs"))
    into("$projectDir/paper/plugins")
}

tasks {

}

能否给出一个打包kotlin-reflect的例子,感谢!

FALLANGELZOU commented 9 months ago

当使用skipKotlin后,我无法手动将kotlin依赖打包(taboo指令不生效),会出现Caused by: java.lang.ClassNotFoundException: kotlinnull.LazyThreadSafetyMode的问题,导致整个插件都无法正常工作

TheFloodDragon commented 9 months ago

当使用skipKotlin后,我无法手动将kotlin依赖打包(taboo指令不生效),会出现Caused by: java.lang.ClassNotFoundException: kotlinnull.LazyThreadSafetyMode的问题,导致整个插件都无法正常工作

要么你就启用isolated加载方式,不重定向Kotlin

要么你就重定向Kotlin:

// Kotlin Version
val kotlinVersion = "1.9.20"
// Escape Function
val String.escapedVersion get() = this.replace(Regex("[._-]"), "")
// Relocate (With ShadowJar)
relocate("kotlin.", "kotlin${kotlinVersion.escapedVersion}.") { exclude(skipRelocateKotlinClasses) }
relocate("kotlinx.coroutines.", "kotlinx.coroutines${coroutineVersion.escapedVersion}.")
relocate("kotlinx.serialization.", "kotlinx.serialization${serializationVersion.escapedVersion}.")

/**
 * 跳过重定向的Kotlin类
 */
val skipRelocateKotlinClasses = setOf(
    "kotlin.annotation.Repeatable",
    "kotlin.annotation.Retention",
    "kotlin.annotation.Target",
    "kotlin.jvm.JvmField",
    "kotlin.jvm.JvmInline",
    "kotlin.jvm.JvmStatic",
    "kotlin.jvm.PurelyImplements",
    "kotlin.Metadata",
    "kotlin.Deprecated",
    "kotlin.ReplaceWith",
)
FALLANGELZOU commented 9 months ago

当使用skipKotlin后,我无法手动将kotlin依赖打包(taboo指令不生效),会出现Caused by: java.lang.ClassNotFoundException: kotlinnull.LazyThreadSafetyMode的问题,导致整个插件都无法正常工作

要么你就启用isolated加载方式,不重定向Kotlin

要么你就重定向Kotlin:

// Kotlin Version
val kotlinVersion = "1.9.20"
// Escape Function
val String.escapedVersion get() = this.replace(Regex("[._-]"), "")
// Relocate (With ShadowJar)
relocate("kotlin.", "kotlin${kotlinVersion.escapedVersion}.") { exclude(skipRelocateKotlinClasses) }
relocate("kotlinx.coroutines.", "kotlinx.coroutines${coroutineVersion.escapedVersion}.")
relocate("kotlinx.serialization.", "kotlinx.serialization${serializationVersion.escapedVersion}.")

/**
 * 跳过重定向的Kotlin类
 */
val skipRelocateKotlinClasses = setOf(
    "kotlin.annotation.Repeatable",
    "kotlin.annotation.Retention",
    "kotlin.annotation.Target",
    "kotlin.jvm.JvmField",
    "kotlin.jvm.JvmInline",
    "kotlin.jvm.JvmStatic",
    "kotlin.jvm.PurelyImplements",
    "kotlin.Metadata",
    "kotlin.Deprecated",
    "kotlin.ReplaceWith",
)

能麻烦给个更详细的例子吗,relocate貌似并不能接受一个lambda函数来执行exclude,之后我倒是尝试过relocate("kotlin.", "kotlin1822.")这种方式,但还是报错了。感觉和taboo的打包逻辑有关

TheFloodDragon commented 9 months ago

上面那个我是用ShadowJar打包的,若要使用taboolib-gradle-plugin打包Kotlin标准库,貌似就没法排除掉跳过重定向的Kotlin类,正如你所说,relocate貌似并不能接受一个lambda函数来执行exclude,

所以还是建议使用ShadowJar来帮助打包插件

plugins {
    id("com.github.johnrengelman.shadow") version "8.1.1"
}
tasks {
    // ShadowJar
    withType<ShadowJar> {
        // Options
        archiveAppendix.set("")
        archiveClassifier.set("")
        archiveVersion.set(rootVersion)
        destinationDirectory.set(file("$rootDir/outs")) // 输出路径自己设置,不设置也行
        // Taboolib
        relocate("taboolib", "$rootGroup.taboolib")
        relocate("org.tabooproject", "$rootGroup.library")
        // Kotlin
        relocate("kotlin.", "kotlin${kotlinVersion.escapedVersion}.") { exclude(skipRelocateKotlinClasses) }
        relocate("kotlinx.coroutines.", "kotlinx.coroutines${coroutineVersion.escapedVersion}.")
        // 这个可以不用,删掉,如果没用到的话
        relocate("kotlinx.serialization.", "kotlinx.serialization${serializationVersion.escapedVersion}.")
    }
}
怪怪的? 怎么感觉我像个ChatGPT。。。。。。。。。。。。。。。。。