Intellij Idea Kotlin多平台:共享多个目标的实际类实现(iOS,macOS)

brtdzjyr  于 2022-12-17  发布在  Kotlin
关注(0)|答案(4)|浏览(200)

我正在开发一个支持JVM、iOS和macOS的Kotlin/Native多平台项目。我的设置包含以下模块:

- common
- ios
- jvm
- macos

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

oprakyz7

oprakyz71#

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的不同的东西,我认为Egor上面的答案更容易理解。
实际上,我们在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
}

虚拟机

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)

}
gopyfrb3

gopyfrb32#

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
    }
  }
}
isr3a4wc

isr3a4wc3#

如果这三个实现完全相同,只需将代码放在common中。expect/actual仅用于不同平台上的“不同”内容

wvmv3b1j

wvmv3b1j4#

如果您使用KotlinDSL,您的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)
        }
    }
}

相关问题