gradle Kotlin本地编译jar和框架

wgeznvg7  于 2023-03-18  发布在  Kotlin
关注(0)|答案(3)|浏览(198)

我正在构建一个适用于Android和iOS的多平台库。我的gradle文件如下所示:

plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.4.0'
}
repositories {
    mavenCentral()
}
group 'com.example'
version '0.0.1'

apply plugin: 'maven-publish'

kotlin {
    jvm()
    // This is for iPhone simulator
    // Switch here to iosArm64 (or iosArm32) to build library for iPhone device
    ios {
        binaries {
            framework()
        }
    }
    sourceSets {
        commonMain {
            dependencies {
                implementation kotlin('stdlib-common')
                implementation("com.ionspin.kotlin:bignum:0.2.2")
            }
        }
        commonTest {
            dependencies {
                implementation kotlin('test-common')
                implementation kotlin('test-annotations-common')
            }
        }
        jvmMain {
            dependencies {
                implementation("com.ionspin.kotlin:bignum:0.2.2")
            }
        }
        jvmTest {
            dependencies {
                implementation kotlin('test')
                implementation kotlin('test-junit')
            }
        }
        iosMain {
        }
        iosTest {
        }
    }
}

configurations {
    compileClasspath
}

我正在使用第三方库,我是这样使用它的:

fun test(value: String): Int {
    return BigDecimal.parseString(value).toBigInteger().intValue()
}

问题是当我构建.jar时,bignum库没有包含在内,当我在Android项目中使用该库时,我收到了一个异常ClassNotFoundException:找不到类“com.离子自旋.Kotlin.bignum.decimal.BigDecimal”。
有没有办法在Android的.jar和iOS的.framework中包含第三方库?

kuhbmx9i

kuhbmx9i1#

虚拟机

因此,我发现生成一个如您所期望的那样工作的Fat JAR的唯一方法是在应用java插件后,在KMP库的project:build.gradle.kts中添加两个 * 自定义gradle任务 *。

plugins {
    [...]
    id("java")
}

[...]

kotlin {
    jvm {
        [...]
        compilations {
            val main = getByName("main")
            tasks {
                register<Copy>("unzip") {
                    group = "library"
                    val targetDir = File(buildDir, "3rd-libs")
                    project.delete(files(targetDir))
                    main.compileDependencyFiles.forEach {
                        println(it)
                        if (it.path.contains("com.")) {
                            from(zipTree(it))
                            into(targetDir)
                        }
                    }
                }
                register<Jar>("fatJar") {
                    group = "library"
                    manifest {
                        attributes["Implementation-Title"] = "Fat Jar"
                        attributes["Implementation-Version"] = archiveVersion
                    }
                    archiveBaseName.set("${project.name}-fat")
                    val thirdLibsDir = File(buildDir, "3rd-libs")
                    from(main.output.classesDirs, thirdLibsDir)
                    with(jar.get() as CopySpec)
                }
            }
            tasks.getByName("fatJar").dependsOn("unzip")
        }

    }
    [...]
}

然后,您必须启动fatJar gradle任务,生成一个 .jar 文件,其中包含从相应 jar 归档中提取的第三个库类。
您可以进一步自定义这两个自定义gradle脚本,以更好地满足您的需求(这里我只在**com.***包中包含依赖项)。

然后,在您的Android应用程序app:build.gradle文件中,您可以像以前那样使用它,或者只需
implementation files('libs/KMLibraryTest001-fat-1.0-SNAPSHOT.jar')

操作系统

当你在你的标题中要求iOS部分时(即使它是你问题的主要主题中的第二个公民),你只需要为你的第三方库使用api而不是implementation,沿着框架的导出选项。

ios() {
    binaries {
        framework() {
            transitiveExport = true // all libraries
            //export(project(":LibA")) // this library project in a transitive way
            //export("your 3rd party lib") // this 3rd party lib in a transitive way
        }
    }
}

你可以在这里找到完整的参考资料。

jqjz2hbq

jqjz2hbq2#

如果您看到Krypto library,它具有

androidMain
jsMain
jvmMain
mingwX64Main
nativPosixMain

这意味着生成5种二进制文件以支持5个平台
令人信服的是,这解释了每个平台都需要自己的二进制文件
例如,
窗口--DLL文件
linux --so文件
java --JAR文件
mac --dylib文件
JAR加载到JVM中,但IOS不使用JVM
分离具有通用逻辑的实用程序函数,并编写面向多个平台的gradle
如果您想从纯多平台开始,可以尝试以下Official Example
或者创建一个subgradle模块,然后创建一个库项目,这在IOS和Android中是通用的
正确记录可能的目标here
我已经创建了一个应用程序,它将二进制文件发布到本地存储库并在MainActivity中重用--您可以获得代码here
修改local.properties for android SDK的位置和使用

gradlew assemble

构建APK并自己测试
打开mylib\build.gradle.kts文件夹,您可以看到目标jvmiosX64jvm用于Android

du7egjpx

du7egjpx3#

如果我是正确的,使用api代替implementation应该可以解决您的问题,尽管我还没有在Native部分尝试过
参见API和实现分离

相关问题