mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-06-01 22:19:18 +02:00
5.1 KiB
5.1 KiB
Skill: KMP Architecture & Source-Set Bridging
Description
Guidelines on managing Kotlin Multiplatform (KMP) source-sets, expected abstractions, networking, database, and platform integration rules.
1. Source-Set Boundaries
commonMain: All business logic, DB entities, API network logic, ViewModels, and UI rendering. NOjava.*orandroid.*imports.androidMain: Android framework integration (Context, system services, NFC hardware, BLE Android bindings).jvmMain/jvmAndroidMain: Shared JVM code between Android and Desktop. Uses themeshtastic.kmp.jvm.androidconvention plugin to bridgejvmandandroidsource sets without manualdependsOnhacks.app/desktop: Host shells. Responsible for Koin DI root wiring,MainKoinModule, host-level UI themes, and running theMeshtasticNavDisplay.
2. Bridging Strategies
- Interface + DI (Preferred): Expose an interface in
core:repositoryorcore:ui(e.g.LocationRepository,MapViewProvider), implement it inandroidMainor the hostapp, and bind it via Koin orCompositionLocal. expect/actual(Restricted): Use only when a platform API cannot be abstracted cleanly (e.g. low-level File I/O mappings,uppercase()Locale helpers). Avoid deep class hierarchies usingexpect/actual.- Naming: Keep
expectinFileIo.kt, but put shared helpers inFileIoUtils.ktto prevent JVM duplicate class errors.
- Naming: Keep
- Shared Helpers: Do not duplicate pure Kotlin logic between
androidMainandjvmMain. Extract to acommonMainhelper.
3. Core Libraries & Constraints
- Concurrency:
kotlinx.coroutines. Useorg.meshtastic.core.common.util.ioDispatcheroverDispatchers.IOdirectly. - Standard Library Replacements:
ConcurrentHashMap->atomicfuor Mutex-guardedmutableMapOf().java.util.concurrent.locks.*->kotlinx.coroutines.sync.Mutex.java.io.*->Okio(BufferedSource/BufferedSink).
- Networking: Pure Ktor. No OkHttp. Ktor
Loggingplugin for debugging. - BLE: Route through
core:bleusing Kable. - Room KMP: Use
factory = { MeshtasticDatabaseConstructor.initialize() }inRoom.databaseBuilder.
4. Hierarchy & Source-Set Conventions
- Hierarchy template first: Prefer Kotlin's default hierarchy template and convention plugins over manual
dependsOn(...)graphs. Manual source-set wiring should be reserved for cases the template cannot model. expect/actualrestraint: Prefer interfaces + DI for platform capabilities; useexpect/actualfor small unavoidable platform primitives. Avoid broad expect/actual class hierarchies when an interface-based boundary is sufficient.- Shared helpers over duplicated lambdas: When
androidMainandjvmMaincontain identical pure-Kotlin logic (formatting, action dispatch, validation), extract tocommonMain. Examples:formatLogsTo(),handleNodeAction(),findNodeByNameSuffix(),MeshtasticAppShell,BaseRadioTransportFactory.
5. Dependency Catalog Aliases
- JetBrains fork aliases: Version catalog aliases for JetBrains-forked AndroidX artifacts use the
jetbrains-*prefix (e.g.,jetbrains-lifecycle-runtime-compose,jetbrains-navigation3-ui). Plainandroidx-*aliases are true Google AndroidX artifacts. Never mix them up incommonMain. - Compose Multiplatform: Version catalog aliases for Compose Multiplatform artifacts use the
compose-multiplatform-*prefix (e.g.,compose-multiplatform-material3,compose-multiplatform-foundation). Never use plainandroidx.composedependencies incommonMain. - Dependencies: Always check
gradle/libs.versions.tomlbefore assuming a library is available.
6. I/O & Serialization
- Okio standard: This project standardizes on Okio (
BufferedSource/BufferedSink). JetBrains recommendskotlinx-io(built on Okio), but this project has not migrated. Do not introducekotlinx-iowithout an explicit decision. - Room KMP: Always use
factory = { MeshtasticDatabaseConstructor.initialize() }inRoom.databaseBuilderandinMemoryDatabaseBuilder. DAOs and Entities reside incommonMain.
7. Build-Logic Conventions
- In
build-logic/convention, prefer lazy Gradle configuration (configureEach,withPlugin, provider APIs). AvoidafterEvaluatein convention plugins unless there is no viable lazy alternative.
8. Onboarding a New Target (Desktop/iOS)
- Ensure all new logic compiles against the KMP core (
jvm(),iosArm64(), etc.). - Do not use platform-specific constructs in
commonMainor you break the iOS/Desktop builds. - Test using
kmpSmokeCompileto verify cross-platform compilation. - For desktop wiring, copy the pattern in
desktop/src/main/kotlin/org/meshtastic/desktop/di/DesktopKoinModule.ktand useNoopStubs.ktto temporarily mock missing platform implementations.
Reference Anchors
- Shared Okio I/O:
core/domain/src/commonMain/kotlin/org/meshtastic/core/domain/usecase/settings/ImportProfileUseCase.kt - Desktop DI Stubs:
desktop/src/main/kotlin/org/meshtastic/desktop/stub/NoopStubs.kt - Version Catalog:
gradle/libs.versions.toml - Convention Plugins:
build-logic/convention/