Kotlin Native编译jar和框架
Kotlin Native compile jar and framework
我正在为 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: Didn't find class “com.ionspin.kotlin.bignum.decimal.BigDecimal”.
有没有办法在 Android 的 .jar 和 iOS 的 .framework 中包含第三方库?
JVM
因此,我发现生成按您预期工作的 Fat JAR 的唯一方法是添加两个 自定义 gradle 任务 在应用 java 插件后你的 KMP 库的 project:build.gradle.kts
。
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 文件,并从中提取相应的第 3 个库 类 jar 个档案。
您可以进一步自定义这两个自定义 gradle 脚本,以更好地满足您的需求(这里我只包括 com. 包名称起始 deps)。
然后在您的 Android 应用程序 app:build.gradle
文件中,您可以照原样使用它,也可以直接使用
implementation files('libs/KMLibraryTest001-fat-1.0-SNAPSHOT.jar')
iOS
当您还要求标题中的 iOS 部分时(即使它是您问题主要主题中的第二公民),您只需要使用 api
而不是 implementation
用于您的第 3 方库以及框架的导出选项。
ios() {
binaries {
framework() {
transitiveExport = true // all libraries
//export(project(":LibA")) // this library project in a trainsitive way
//export("your 3rd party lib") // this 3rd party lib in a transitive way
}
}
}
您可以找到完整的参考资料 here。
如果我使用 api
而不是 implementation
是正确的,应该可以解决您的问题,尽管我还没有在 Native 部分尝试过
如果您看到 Krypto library,它有
androidMain
jsMain
jvmMain
mingwX64Main
nativPosixMain
这意味着生成了 5 种二进制文件以支持 5 个平台
令人信服的是,这解释了每个平台都需要自己的二进制文件
例如,
windows -- DLL
文件
linux -- so
文件
java -- JAR
文件
mac -- dylib
文件
JAR 被加载到 JVM 中,但是 IOS 不使用 JVM
将具有共同逻辑的实用程序函数分开并编写 gradle 以针对多个平台
如果你想从纯多平台开始,你可以试试这个Official Example
或者创建一个子 gradle 模块并创建一个库项目,这对 IOS 以及 Android
是通用的
可能的目标已正确记录here
我创建了一个将二进制文件发布到本地存储库并在 MainActivity
中重复使用的应用程序——您可以获得代码 here
修改 local.properties
为 android SDK 位置并使用
gradlew assemble
构建 APK 并自行测试
打开mylib\build.gradle.kts
文件夹可以看到目标jvm
和iosX64
,jvm
用于android
我正在为 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: Didn't find class “com.ionspin.kotlin.bignum.decimal.BigDecimal”.
有没有办法在 Android 的 .jar 和 iOS 的 .framework 中包含第三方库?
JVM
因此,我发现生成按您预期工作的 Fat JAR 的唯一方法是添加两个 自定义 gradle 任务 在应用 java 插件后你的 KMP 库的 project:build.gradle.kts
。
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 文件,并从中提取相应的第 3 个库 类 jar 个档案。
您可以进一步自定义这两个自定义 gradle 脚本,以更好地满足您的需求(这里我只包括 com. 包名称起始 deps)。
然后在您的 Android 应用程序 app:build.gradle
文件中,您可以照原样使用它,也可以直接使用
implementation files('libs/KMLibraryTest001-fat-1.0-SNAPSHOT.jar')
iOS
当您还要求标题中的 iOS 部分时(即使它是您问题主要主题中的第二公民),您只需要使用 api
而不是 implementation
用于您的第 3 方库以及框架的导出选项。
ios() {
binaries {
framework() {
transitiveExport = true // all libraries
//export(project(":LibA")) // this library project in a trainsitive way
//export("your 3rd party lib") // this 3rd party lib in a transitive way
}
}
}
您可以找到完整的参考资料 here。
如果我使用 api
而不是 implementation
是正确的,应该可以解决您的问题,尽管我还没有在 Native 部分尝试过
如果您看到 Krypto library,它有
androidMain
jsMain
jvmMain
mingwX64Main
nativPosixMain
这意味着生成了 5 种二进制文件以支持 5 个平台
令人信服的是,这解释了每个平台都需要自己的二进制文件
例如,
windows -- DLL
文件
linux -- so
文件
java -- JAR
文件
mac -- dylib
文件
JAR 被加载到 JVM 中,但是 IOS 不使用 JVM
将具有共同逻辑的实用程序函数分开并编写 gradle 以针对多个平台
如果你想从纯多平台开始,你可以试试这个Official Example
或者创建一个子 gradle 模块并创建一个库项目,这对 IOS 以及 Android
是通用的可能的目标已正确记录here
我创建了一个将二进制文件发布到本地存储库并在 MainActivity
中重复使用的应用程序——您可以获得代码 here
修改 local.properties
为 android SDK 位置并使用
gradlew assemble
构建 APK 并自行测试
打开mylib\build.gradle.kts
文件夹可以看到目标jvm
和iosX64
,jvm
用于android