Skip to content

fix(desktop): unbreak release crash via correct ProGuard rules#5236

Merged
jamesarich merged 2 commits into
meshtastic:mainfrom
jamesarich:fix/desktop-release-proguard
Apr 23, 2026
Merged

fix(desktop): unbreak release crash via correct ProGuard rules#5236
jamesarich merged 2 commits into
meshtastic:mainfrom
jamesarich:fix/desktop-release-proguard

Conversation

@jamesarich

Copy link
Copy Markdown
Collaborator

Summary

Desktop release v2.7.14-internal.69 crashed on launch on macOS, Windows, and Linux arm64 .deb. Root cause: compose-jb's standalone ProGuard 7.7 task does not auto-discover META-INF/proguard/*.pro consumer rules from dependency jars (only R8 on Android does — see Guardsquare/proguard#423). Reflective lookups (e.g. ktor's KotlinxSerializationJsonExtensionProvider via ServiceLoader) failed at runtime with ServiceConfigurationError.

This PR resets the rules to the JetBrains-recommended approach: a single static shared-rules.pro that inlines every consumer rule we need on desktop. On Android, R8 still auto-discovers these from the jars, so the inlined copies are harmless duplicates.

Changes

  • config/proguard/shared-rules.pro — inlines consumer rules from kotlinx-coroutines, kotlinx-serialization, kotlinx-datetime, ktor, androidx.annotation, androidx.datastore. Adds explicit -keep for ktor's KotlinxSerializationExtensionProvider impls (consumer rule keeps the META-INF/services file but not the impl class). Removes broad Compose package keeps (-dontoptimize is the real defence against fix(app): add R8 keep rules for Compose animation/runtime/ui #5146) and qrcode-kotlin keeps (statically called via QRCode.ofSquares() — no reflection in our code). Preserves targeted keeps for Wire ADAPTER fields, Koin annotation source classes, the bundled SQLite JNI bridge, and our specific Room database.
  • desktop/proguard-rules.pro — slimmed to JVM-specifics: -dontprocesskotlinmetadata (ProGuard 7.7 + Kotlin 2.3 NPE workaround), -dontoptimize, narrow -dontwarn lines for jSerialComm Android stubs, Wire AndroidMessage, three specific Vico ColorScale* classes, and Kotlin 2.3+ stdlib intrinsics not on JDK 17.
  • desktop/build.gradle.kts — comment block clarifying that consumer rules must be inlined manually for desktop.

Verification

  • ./gradlew spotlessApply detekt
  • ./gradlew :app:assembleFdroidRelease ✅ (Android R8)
  • ./gradlew :desktop:createReleaseDistributable
  • Obfuscated desktop binary launches on Linux x64, connects to a real radio, processes mesh packets, no exceptions, no animation freeze.

Untested platforms

macOS, Windows, Linux arm64 .deb (no local hardware). Crash signature was platform-agnostic (ServiceLoader / reflective lookups), but please verify on at least one non-Linux runner before tagging the next release.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

@github-actions github-actions Bot added the bugfix PR tag label Apr 23, 2026
Per R8_Configuration_Analysis.md:

- Remove broad package-wide Compose keeps (androidx.compose.{runtime,ui,animation,foundation,material3}.**). The primary defence against CMP 1.11 optimizer folding is -dontoptimize; package-wide keeps are redundant and subsume library consumer rules. If animations freeze in future CMP releases, replace with class-level keeps on Composer/ComposerImpl/ComposeRuntimeFlags/ComposeStackTraceMode only.

- Remove qrcode-kotlin keeps (io.github.g0dkar.qrcode.** and qrcode.**). QRCode.ofSquares().build() is called statically throughout the codebase; no Class.forName or ServiceLoader reflection detected. R8 can resolve this without manual keeps.

- Consolidate keep rules into minimal targeted form per keep-rules-impact-hierarchy guidance. Inline all consumer rules in shared-rules.pro (desktop ProGuard does not auto-discover META-INF/proguard/*.pro as R8 does).

- Verified: Android release builds (assembleFdroidRelease) and desktop release (createReleaseDistributable) both succeed. Desktop binary launches without animation freeze.

Deferred: androidx.sqlite.driver.bundled.** JNI symbol enumeration (low priority; package-wide keep is not a size concern).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jamesarich jamesarich force-pushed the fix/desktop-release-proguard branch 3 times, most recently from 9ce0b4b to 904ad1c Compare April 23, 2026 20:31
The previous group-wide eachDependency rule pinned every artifact in the
`androidx.compose.material` group to 1.7.8, which actively downgraded
`material-ripple` from CMP-aligned 1.11.0-rc01.

Narrow the pin to the `:material` (M2 main) artifact only. M2 is needed
because maps-compose-widgets (google flavor) requests it without a version
relying on a BOM that we exclude. material-ripple now resolves to the
CMP-aligned 1.11.0 line as JetBrains intends.

Verified :app:assembleGoogleDebug, :app:assembleFdroidDebug, :desktop:assemble.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jamesarich jamesarich force-pushed the fix/desktop-release-proguard branch from 904ad1c to c1f4823 Compare April 23, 2026 20:31
@jamesarich jamesarich added this pull request to the merge queue Apr 23, 2026
Merged via the queue into meshtastic:main with commit 2e6730d Apr 23, 2026
11 checks passed
@jamesarich jamesarich deleted the fix/desktop-release-proguard branch April 23, 2026 21:54
Copilot AI pushed a commit that referenced this pull request Apr 24, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix PR tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant