Status Update
Comments
da...@google.com <da...@google.com> #2
Can you share your Gradle build file and how room-compiler
is being setup? The error is indicating that the Room processor likely did not run which in turns means the generated implementation of the database was not created and can't be found.
fa...@gmail.com <fa...@gmail.com> #3
This is my gradle file. I need to re -explain it runs well in Android, iOS, and Desktop's debug.It only crash when runRelease on desktop.
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidApplication)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
alias(libs.plugins.kotlinCocoapods)
alias(libs.plugins.googleKsp)
alias(libs.plugins.kotlinSerialization)
alias(libs.plugins.androidxRoom)
}
kotlin {
androidTarget {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
iosX64()
iosArm64()
iosSimulatorArm64()
cocoapods {
summary = "Some description for the Shared Module"
homepage = "Link to the Shared Module homepage"
version = "1.0"
ios.deploymentTarget = "13.0"
podfile = project.file("../iosApp/Podfile")
framework {
baseName = "ComposeApp"
isStatic = true
}
}
jvm("desktop")
sourceSets {
val desktopMain by getting
androidMain.dependencies {
implementation(compose.preview)
implementation(libs.androidx.activity.compose)
}
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.navigation)
// Serialization
implementation(libs.kotlinx.serialization.json)
// Room
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.sqlite.bundled)
}
desktopMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutines.swing)
}
}
}
android {
namespace = "xxx"
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
applicationId = "xxx"
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
versionCode = 1
versionName = "1.0"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
debugImplementation(compose.uiTooling)
}
compose.desktop {
application {
mainClass = "xxx.MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "xxx"
packageVersion = "1.0.0"
}
}
}
dependencies {
kspCommonMainMetadata(libs.koin.ksp.compiler)
listOf(
"kspAndroid",
"kspDesktop",
"kspIosX64",
"kspIosArm64",
"kspIosSimulatorArm64"
).forEach {
add(it, libs.androidx.room.compiler)
}
}
project.tasks.withType(KotlinCompilationTask::class.java).configureEach {
if (name != "kspCommonMainKotlinMetadata") {
dependsOn("kspCommonMainKotlinMetadata")
}
}
kotlin.sourceSets.commonMain {
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}
room {
schemaDirectory("$projectDir/schemas")
}
da...@google.com <da...@google.com> #4
Does release
have some type of obfuscation? The generated database file is found via reflection and if the class is renamed due to obfuscation, that could be a cause. For room-runtime
ships with proguard rules
Also, one thing in the build file is you seem to have an outdated workaround where Room is applied to the common source set and a manual dependency to the KSP generated in metadata is added, those workarounds should be removed if using the latest version. Specifically the lines:
// in dependencies
kspCommonMainMetadata(libs.koin.ksp.compiler)
project.tasks.withType(KotlinCompilationTask::class.java).configureEach {
if (name != "kspCommonMainKotlinMetadata") {
dependsOn("kspCommonMainKotlinMetadata")
}
}
kotlin.sourceSets.commonMain {
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}
I'm not sure if it'll solve your issue but wanted to call them out.
fa...@gmail.com <fa...@gmail.com> #5
These codes are because I use koin-annotations. If I delete any of them, it will cause koin-annotations to be unable to generate code normally.
da...@google.com <da...@google.com> #6
Gotcha - I think the issue is obfuscation then.
Can you try disabling it:
compose.desktop {
application {
buildTypes.release.proguard.obfuscate = false
...
}
}
da...@google.com <da...@google.com> #7
Two more alternatives:
-
Include a proguard file with the same rule specified by Room's included one:
-keep class * extends androidx.room.RoomDatabase { void <init>(); }
via the DSLbuildTypes.release.proguard.configurationFiles
-
Include a 'factory' in your database builder that uses the database constructor in a more manual way, avoiding the reflection that is for convinience:
Room.inMemoryDatabaseBuilder<MyDatabase>(
factory = { MyDatabaseCtor.initialize() }
)
ap...@google.com <ap...@google.com> #8
Project: platform/frameworks/support
Branch: androidx-main
Author: Daniel Santiago Rivera <
Link:
Include Proguard rules in Room's runtime JVM artifacts
Expand for full commit details
Include Proguard rules in Room's runtime JVM artifacts
Bug: 392657750
Test: Manually on sample app with ./gradlew runRelease
Change-Id: I43950728d7227e13979945a64a118e55270ed4e0
Files:
- M
room/room-runtime/build.gradle
- M
room/room-runtime/src/androidMain/proguard-rules.pro
- A
room/room-runtime/src/jvmMain/resources/META-INF/com.android.tools/proguard/room.pro
- A
room/room-runtime/src/jvmMain/resources/META-INF/com.android.tools/r8/room.pro
- A
room/room-runtime/src/jvmMain/resources/META-INF/proguard/room.pro
Hash: 977f11f1f2adcc7ed85c109eca38b96dfd2c3f8d
Date: Tue Jan 28 12:56:52 2025
da...@google.com <da...@google.com>
pr...@google.com <pr...@google.com> #9
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.room:room-runtime:2.7.0-beta01
androidx.room:room-runtime-android:2.7.0-beta01
androidx.room:room-runtime-iosarm64:2.7.0-beta01
androidx.room:room-runtime-iossimulatorarm64:2.7.0-beta01
androidx.room:room-runtime-iosx64:2.7.0-beta01
androidx.room:room-runtime-jvm:2.7.0-beta01
androidx.room:room-runtime-linuxarm64:2.7.0-beta01
androidx.room:room-runtime-linuxx64:2.7.0-beta01
androidx.room:room-runtime-macosarm64:2.7.0-beta01
androidx.room:room-runtime-macosx64:2.7.0-beta01
fa...@gmail.com <fa...@gmail.com> #10
After upgrading 2.7.0-beta01, this crash still exists.
Caused by: java.lang.RuntimeException: Cannot find implementation for com.develop.ximi.db.AppDatabase. AppDatabase_Impl does not exist. Is Room annotation processor correctly configured?
Component used: room-runtime, room-compiler, sqlite-bundled Version used: room: 2.7.0-beta01, sqlite: 2.5.0-beta01
da...@google.com <da...@google.com> #11
Re-opening since this doesn't seem to be resolved.
I'm not sure what else we need to include in the artifact, the JVM .jar
now contains rules to avoid removing the default no-arg constructor:
❯ unzip -l /Users/danysantiago/Downloads/room-runtime-jvm-2.7.0-beta01.jar
Archive: /Users/danysantiago/Downloads/room-runtime-jvm-2.7.0-beta01.jar
Length Date Time Name
--------- ---------- ----- ----
0 02-01-1980 00:00 META-INF/
25 02-01-1980 00:00 META-INF/MANIFEST.MF
703 02-01-1980 00:00 META-INF/room-runtime.kotlin_module
...
0 02-01-1980 00:00 META-INF/com.android.tools/
0 02-01-1980 00:00 META-INF/com.android.tools/proguard/
62 02-01-1980 00:00 META-INF/com.android.tools/proguard/room.pro
0 02-01-1980 00:00 META-INF/com.android.tools/r8/
62 02-01-1980 00:00 META-INF/com.android.tools/r8/room.pro
0 02-01-1980 00:00 META-INF/proguard/
62 02-01-1980 00:00 META-INF/proguard/room.pro
0 02-01-1980 00:00 META-INF/androidx/
0 02-01-1980 00:00 META-INF/androidx/room/
0 02-01-1980 00:00 META-INF/androidx/room/room-runtime/
But it seems that is not enough?
However if I create the same proguard file and include it via the DSL it works:
compose.desktop {
application {
mainClass = "org.example.project.MainKt"
buildTypes.release.proguard {
configurationFiles.from(project.layout.projectDirectory.file("proguard.pro"))
}
}
}
It seems the issue might be with Kotlin Gradle Plugin consuming proguard rules in dependencies?
lz...@gmail.com <lz...@gmail.com> #12
If turn off the obfuscation, there is no error, but it's certainly not a good solution
compose.desktop {
application {
buildTypes.release{
proguard {
isEnabled = true // false to disable proguard
optimize = true
obfuscate = true // if set to false, no err. default is false.
// additional rule
configurationFiles.from(project.layout.projectDirectory.file("proguard-rules.pro"))
}
}
}
}
After using version 2.7.0-beta01, I also get "AppDatabase_Impl does not exist. Is Room annotation processor correctly configured?"
then I used "-keep" on the database code and generated code path. eg:
-keep class com.example.room.** {* ;}
but I got the new error, So now I really don't know how to do it。
SLF4J(I): Connected with provider of type [ch.qos.logback.classic.spi.LogbackServiceProvider]
Exception in thread "AWT-EventQueue-0" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at ayr.a(KClassUtil.jvmAndroid.kt:44)
at ayr.a(KClassUtil.jvmAndroid.kt:29)
at com.example.room.di.DatabaseCreatorFactory_jvmKt$getDatabaseBuilder$$inlined$databaseBuilder$default$1.invoke(Room.jvm.kt:57)
at com.example.room.di.DatabaseCreatorFactory_jvmKt$getDatabaseBuilder$$inlined$databaseBuilder$default$1.invoke(Room.jvm.kt:57)
at awc$a.a(RoomDatabase.jvmNative.kt:516)
at com.example.room.di.DatabaseCreatorFactory_jvmKt.getRoomDatabase(DatabaseCreatorFactory.jvm.kt:35)
at com.example.room.di.DatabaseCreatorFactory.createRoomDatabase(DatabaseCreatorFactory.jvm.kt:12)
at com.example.room.di.LocalDb.db_delegate$lambda$0(DatabaseCreatorFactory.jvm.kt:17)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:83)
at com.example.room.di.LocalDb.getDb(DatabaseCreatorFactory.jvm.kt:17)
at org.lodestone.app.c.invokeSuspend(Main.kt:22)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
at vr.a(FlushCoroutineDispatcher.skiko.kt:93)
at vr.invoke(FlushCoroutineDispatcher.skiko.kt:80)
at vo.a(FlushCoroutineDispatcher.skiko.kt:102)
at vo.a(FlushCoroutineDispatcher.skiko.kt:80)
at adn.b(ComposeSceneRecomposer.skiko.kt:91)
at abg.a(BaseComposeScene.skiko.kt:165)
at ade.a(ComposeSceneMediator.desktop.kt:574)
at ade.invoke(ComposeSceneMediator.desktop.kt:572)
at aob.b(SwingInteropContainer.desktop.kt:229)
at acr.onRender(ComposeSceneMediator.desktop.kt:572)
at org.jetbrains.skiko.SkiaLayer.update$skiko(SkiaLayer.awt.kt:533)
at org.jetbrains.skiko.redrawer.AWTRedrawer.update(AWTRedrawer.kt:54)
at org.jetbrains.skiko.redrawer.Direct3DRedrawer.redrawImmediately(Direct3DRedrawer.kt:74)
at org.jetbrains.skiko.SkiaLayer.tryRedrawImmediately(SkiaLayer.awt.kt:373)
at org.jetbrains.skiko.SkiaLayer.paint(SkiaLayer.awt.kt:346)
at aeg.paint(WindowSkiaLayerComponent.desktop.kt:64)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:952)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1128)
at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:952)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1128)
at aqv.a(Window.desktop.kt:630)
at aqv.invoke(Window.desktop.kt:615)
at aoy.a(AwtWindow.desktop.kt:78)
at aoy.invoke(AwtWindow.desktop.kt:76)
at anc.a(UpdateEffect.desktop.kt:59)
at anc.invoke(UpdateEffect.desktop.kt:55)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2442)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:505)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:261)
at amy.b(UpdateEffect.desktop.kt:55)
at amy.a(UpdateEffect.desktop.kt:64)
at amy.invoke(UpdateEffect.desktop.kt:47)
at androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:82)
at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:1364)
at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:992)
at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1013)
at androidx.compose.runtime.Recomposer.composeInitial$runtime(Recomposer.kt:1150)
at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:649)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:635)
at aoq.invokeSuspend(Application.desktop.kt:221)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [abx$b@4d3249cd, androidx.compose.runtime.BroadcastFrameClock@4da3912d, StandaloneCoroutine{Cancelling}@7be3a417, vo@55ce55d]
Caused by: java.lang.ExceptionInInitializerError
at azs.a(AtomicFU.kt:39)
at azs.a(AtomicFU.kt:41)
at axg.<init>(CloseBarrier.kt:43)
at awc.<init>(RoomDatabase.jvmNative.kt:77)
at com.example.room.database.AppDatabase.<init>(AppDatabase.kt:19)
at com.example.room.database.AppDatabase_Impl.<init>(AppDatabase_Impl.kt:33)
... 74 more
Caused by: java.lang.IllegalArgumentException: Must be integer type
at java.base/java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:417)
at java.base/java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdater.java:93)
at azt.<clinit>(AtomicFU.kt:315)
... 80 more
[Incubating] Problems report is available at: file:///E:/libs/kmp/desktop-template/build/reports/problems/problems-report.html
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.11.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 33s
46 actionable tasks: 3 executed, 43 up-to-date
da...@google.com <da...@google.com> #13
So it turns out Proguard for KMP Desktop does not consume library rules like in Android (
re Caused by: java.lang.ExceptionInInitializerError
, can you try with Room version 2.7.0-rc01 ? We removed the usages of AtomicFu from the JVM / Android variants and based on my testing and after adding the progaurd rule -keep class * extends androidx.room.RoomDatabase { <init>(); }
and enabling obfuscation, things work for me.
Description
Component used: room-runtime, room-compiler, sqlite-bundled Version used: room: 2.7.0-alpha12, sqlite: 2.5.0-alpha12 Devices/Android versions reproduced on: MacBook Pro M2
I got crash with runRelease on desktop, but it works fine on debug and other target.