Я создаю проект KMP, который поддерживает Android, iOS, рабочий стол (jvm) и Интернет (wasmJs)... Внутри я реализую комнату для хранения базы данных.
Поскольку WasmJS не поддерживает Room, я создал новый набор исходного кода для Android, iOS и настольных компьютеров и назвал его nonJS.
Вот мой градиент:
kotlin {
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
moduleName = "data"
browser {
commonWebpackConfig {
outputFileName = "composeApp.js"
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
static = (static ?: mutableListOf()).apply {
// Serve sources to debug inside browser
add(project.projectDir.path)
}
}
}
}
binaries.executable()
}
androidTarget {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
}
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "data"
isStatic = true
}
}
jvm("desktop")
@OptIn(ExperimentalKotlinGradlePluginApi::class)
applyDefaultHierarchyTemplate {
// create a new group that
// depends on `common`
common {
// Define group name without
// `Main` as suffix
group("nonJs") {
// Provide which targets would
// be part of this group
withAndroidTarget()
withIos()
withJvm()
}
}
}
sourceSets {
all{
languageSettings {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions{
freeCompilerArgs.add("-Xexpect-actual-classes")
}
}
}
commonMain.dependencies {
api(project(":domain"))
implementation(libs.ktor.client.logging)
implementation(libs.ktor.client.content.negotiation)
}
val nonJsMain by getting {
dependencies {
api(libs.room.runtime)
implementation(libs.sqlite.bundled)
}
}
androidMain.dependencies {
implementation(libs.ktor.client.android)
implementation(libs.ktor.client.okhttp)
implementation(libs.paging.room)
}
iosMain.dependencies {
implementation(libs.ktor.client.darwin)
}
val desktopMain by getting {
dependencies {
implementation(libs.ktor.client.okhttp)
}
}
wasmJsMain.dependencies {
implementation(libs.ktor.client.js)
}
}
task("testClasses")
}
Затем я создал ожидаемый построитель баз данных для этих платформ в папке, отличной от JS.
База данныхBuilder.kt
expect class DatabaseBuilder() {
fun databaseBuilder(): RoomDatabase.Builder<AppDatabase>
}
Затем я начал реализовывать реальные файлы
пример DatabaseBuilder.jvm.kt
actual class DatabaseBuilder {
actual fun databaseBuilder(): RoomDatabase.Builder<AppDatabase> {
val dbFile = File(System.getProperty("java.io.tmpdir"), "movies_database.db")
return Room.databaseBuilder<AppDatabase>(
name = dbFile.absolutePath,
)
}
}
Также DatabaseBuilder.iOS.kt
actual class DatabaseBuilder {
actual fun databaseBuilder(): RoomDatabase.Builder<AppDatabase> {
val dbFilePath = NSHomeDirectory() + "/movies_database.db"
return Room.databaseBuilder<AppDatabase>(
name = dbFilePath,
factory = { AppDatabase::class.instantiateImpl() }
)
}
}
Теперь проблема в следующем:
Я думаю, что что-то не так с моим блоком объявлений, отличным от JS.
@OptIn(ExperimentalKotlinGradlePluginApi::class)
applyDefaultHierarchyTemplate {
// create a new group that
// depends on `common`
common {
// Define group name without
// `Main` as suffix
group("nonJs") {
// Provide which targets would
// be part of this group
withAndroidTarget()
withIos()
withJvm()
}
}
}
Любая помощь с этим?? ИЛИ Есть ли лучший подход к моему проекту??
Я узнал в чем дело... Как и ожидалось, проблема была в моей иерархии.
Неправильная иерархия:
@OptIn(ExperimentalKotlinGradlePluginApi::class)
applyDefaultHierarchyTemplate {
common {
group("nonJs") {
withAndroidTarget()
withIos()
withJvm()
}
}
}
Что приводит к этому графику:
Как видите, цель iOSMain не существует... Вместо этого iOS разделена на основные компоненты IosArm64 и IosX64... Вот почему мои классы iOS в папке iOSMain не смогли разрешить никакие зависимости.
Правильная иерархия:
@OptIn(ExperimentalKotlinGradlePluginApi::class)
applyDefaultHierarchyTemplate {
common {
group("nonJs") {
withAndroidTarget()
withJvm()
group("ios") {
withIos()
}
}
}
}
Что приводит к этому графику:
Как вы можете видеть... Здесь Ios создается отдельной группой внутри nonJs... После этого IosArm64 и IosX64 добавляются в "iOSMain". Таким образом, мои классы iOS в папке iOSMain могли разрешать зависимости.