Kotlin Multiplatform:共享多个目标(iOS、macOS)的实际类实现



我正在开发一个支持 JVM、iOS 和 macOS 的 Kotlin/Native Multiplatform 项目。我的设置具有以下模块:

- common
- ios
- jvm
- macos

我想使用一些本机代码作为actual类,并将expected类放在common中。但是,对于多个目标(iOS 和 macOS),实际的类实现是相同的。有没有办法设置我的源代码(也许在 Gradle 中),这样我就不必维护实际类的 2 个相同副本?

Stately有一个相当复杂的配置。 iOS 和 Macos 共享所有相同的代码。

要构建项目,有commonMainnativeCommonMain取决于此,实际上appleMain这取决于nativeCommonMain

commonMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
}
}
jvmMain {
dependsOn commonMain
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
}
}
nativeCommonMain {
dependsOn commonMain
}
appleMain {
dependsOn nativeCommonMain
}
configure([iosX64Main, iosArm64Main, macosMain, iosArm32Main]) {
dependsOn appleMain
}

这种结构可能比你需要的更深,但我们需要一些不同的东西来用于 linux 和 windows。我认为埃戈尔上面的答案更容易理解。

我们实际上在 Stately 中定义了多平台原子,因此您可以将它们用作灵感,或者实际上只是使用库本身。

https://github.com/touchlab/Stately

常见

expect class AtomicInt(initialValue: Int) {
fun get(): Int
fun set(newValue: Int)
fun incrementAndGet(): Int
fun decrementAndGet(): Int
fun addAndGet(delta: Int): Int
fun compareAndSet(expected: Int, new: Int): Boolean
}

JVM

actual typealias AtomicInt = AtomicInteger

本地

actual class AtomicInt actual constructor(initialValue:Int){
private val atom = AtomicInt(initialValue)
actual fun get(): Int = atom.value
actual fun set(newValue: Int) {
atom.value = newValue
}
actual fun incrementAndGet(): Int = atom.addAndGet(1)
actual fun decrementAndGet(): Int = atom.addAndGet(-1)
actual fun addAndGet(delta: Int): Int = atom.addAndGet(delta)
actual fun compareAndSet(expected: Int, new: Int): Boolean = atom.compareAndSet(expected, new)
}

在 Okio 中,我们声明了两个额外的源代码集,nativeMainnativeTest,并将内置的本机源代码集配置为依赖于它们:

apply plugin: 'org.jetbrains.kotlin.multiplatform'
kotlin {
iosX64()
iosArm64()
linuxX64()
macosX64()
mingwX64('winX64')
sourceSets {
nativeMain {
dependsOn commonMain
}
nativeTest {
dependsOn commonTest
}
configure([iosX64Main, iosArm64Main, linuxX64Main, macosX64Main, winX64Main]) {
dependsOn nativeMain
}
configure([iosX64Test, iosArm64Test, linuxX64Test, macosX64Test, winX64Test]) {
dependsOn nativeTest
}
}
}

如果所有三个实现都相同,只需将该代码放在common中即可。expect/actual仅用于不同平台上不同的事物

如果你使用 Kotlin DSL,你的 build.gradle.kts 文件可能如下所示:

kotlin {
android()

listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "yourframeworkname"
}
}
sourceSets {
val commonMain by getting {
dependencies {
...
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting
val androidTest by getting
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
}
val iosX64Test by getting
val iosArm64Test by getting
val iosSimulatorArm64Test by getting
val iosTest by creating {
dependsOn(commonTest)
iosX64Test.dependsOn(this)
iosArm64Test.dependsOn(this)
iosSimulatorArm64Test.dependsOn(this)
}
}
}

最新更新