Migrate to Kotlin Multiplatform (Android, JVM, iOS)#1
Merged
Conversation
Make the library callable from KMP commonMain so consumers don't have
to gate logging behind expect/actual or platform-specific source sets.
Source layout: src/main → src/commonMain. Platform-touching code is
extracted behind two seams in commonMain:
- expect fun platformLog(...) — Logcat on Android, println on JVM, NSLog
on iOS.
- expect fun resolveCallerInfo() — JVM stack walk shared by Android +
JVM via a jvmCommonMain intermediate source set; null on iOS where
Kotlin/Native lacks a portable equivalent.
- expect helpers for currentTimeMs / currentThreadName / log-timestamp
formatting (Platform.kt) — keeps PrettyLoggingService and
LogBreadcrumbs.formatted() portable.
LogBreadcrumbs.dumpToFile(Context) moves to androidMain as a top-level
extension on the LogBreadcrumbs object. The buffer itself is portable
(ArrayDeque instead of ConcurrentLinkedDeque — accepts that concurrent
logging may very rarely drop a single breadcrumb in exchange for
KMP-portability without an atomicfu dep).
API surface preserved for Android consumers: Log.{d,i,w,e,wtf,network,
timed}, PrettyLog.init, LogBreadcrumbs.{record,getEntries,clear,
dumpToFile} all unchanged. Version bumps to 0.2.0.
Build: AGP 8.7.3 / Kotlin 1.9.25 / Gradle 8.9, no version changes.
Maven publication produces the standard KMP shape (root metadata
artifact + per-target variants prettylog-android / prettylog-jvm /
prettylog-iosX64 / prettylog-iosArm64 / prettylog-iosSimulatorArm64).
JitPack supports KMP publishing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Make PrettyLog callable from KMP
commonMainso consumers don't have to gate logging behind their ownexpect/actualdeclarations or platform-specific source sets.prettylog-androidvariant; existing call sites compile against the sameLog.{d,i,w,e,wtf,network,timed},PrettyLog.init, andLogBreadcrumbs.{record,getEntries,clear,dumpToFile}API.iosX64,iosArm64,iosSimulatorArm64) ship the same API.0.2.0to flag the binary-shape change.What changed
Source layout —
src/main→src/commonMain. Platform-touching code is extracted behind seams in commonMain:expect fun platformLog(...)— Logcat on Android,printlnon JVM,NSLogon iOS.expect fun resolveCallerInfo()— JVM stack walk shared by Android + JVM via ajvmCommonMainintermediate source set; returnsnullon iOS where Kotlin/Native lacks a portable equivalent (the bordered output simply omits the call-site header).expecthelpers inPlatform.ktforcurrentTimeMs(),currentThreadName(), and theHH:mm:ss.SSSlog-timestamp format used byBreadcrumbEntry.formatted().LogBreadcrumbs— buffer logic stays in commonMain;dumpToFile(Context)moves toandroidMainas a top-level extension on theLogBreadcrumbsobject so the existing call site (LogBreadcrumbs.dumpToFile(applicationContext)) compiles unchanged.Three implementation choices worth flagging
ConcurrentLinkedDeque→ArrayDequein the breadcrumb buffer. ArrayDeque is the only KMP-portable deque without pulling inkotlinx-atomicfuas a dep. Trade-off: high-concurrency logging may very rarely drop a single breadcrumb. Acceptable for a debug tool; if strict thread-safety becomes a requirement, the next move iskotlinx.atomicfu.locks.synchronizedaround the buffer ops.kotlin.system.measureTimeMillis→kotlin.time.measureTimedValueinLog.timed. The originalvar result: T+ assign-inside-lambda pattern is rejected by Kotlin/Native;measureTimedValueis the KMP-portable equivalent (still@OptIn(ExperimentalTime::class)in 1.9, stabilized in 2.0).@kotlin.jvm.Volatile→@kotlin.concurrent.VolatileonPrettyLog.service. The latter is the KMP-portable annotation introduced in Kotlin 1.9.Test plan
./gradlew :prettylog:assemble— Android AAR (debug + release), JVM JAR, all three iOS klibs compile cleanly./gradlew :prettylog:publishToMavenLocal— produces the standard KMP publication: root metadata artifactprettylog+prettylog-android,prettylog-jvm,prettylog-iosx64,prettylog-iosarm64,prettylog-iossimulatorarm640.2.0into a downstream Android consumer and verify the existing call sites still link without changesNSLogoutput and the stack-trace-attached error path🤖 Generated with Claude Code