Skip to content

Commit 19075c1

Browse files
authored
feat(kmp): base58 as first KMP module behind a shared-core XCFramework umbrella (#1201)
Establishes the umbrella model for cross-platform code sharing: - kmp/shared-core becomes a thin aggregator that api-exports real KMP modules and publishes ONE SharedCore XCFramework (KMMBridge/SPM) so iOS consumes everything through a single import. It owns no logic itself. - :libs:encryption:base58 becomes the first real KMP module (the pilot): pure Base58 in commonMain, JDK-only helpers (encodeChecked/decodeChecked/ hashTwice/decodeToBigInteger) in androidMain, iOS targets via the default hierarchy template (no manual source-set wiring). shared-core re-exports it. - The base58.json cross-platform vector gate now runs on BOTH the JVM and native targets (commonTest + a readResource expect/actual). - All 9 Android consumers keep depending on :libs:encryption:base58 unchanged — the KMP module still exposes the Android variant. - Adds a flipcash.kmp.library convention plugin (registered; to be adopted by the next KMP modules). Verified: base58 iOS compile, host vector gate, all 9 consumers + app compile, and :kmp:shared-core:spmDevBuild produces SharedCore.xcframework.
1 parent 3244948 commit 19075c1

21 files changed

Lines changed: 373 additions & 270 deletions

File tree

‎Package.swift‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// swift-tools-version:5.9
2+
import PackageDescription
3+
4+
let packageName = "SharedCore"
5+
6+
let package = Package(
7+
name: packageName,
8+
platforms: [
9+
.iOS(.v15)
10+
],
11+
products: [
12+
.library(
13+
name: packageName,
14+
targets: [packageName]
15+
),
16+
],
17+
targets: [
18+
.binaryTarget(
19+
name: packageName,
20+
path: "./kmp/shared-core/build/XCFrameworks/debug/\(packageName).xcframework"
21+
)
22+
,
23+
]
24+
)

‎apps/flipcash/app/build.gradle.kts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ androidComponents {
175175

176176
dependencies {
177177
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
178+
// KMP shared core — consumed transitively via :libs:encryption:base58 but declared
179+
// explicitly so the app's own code can reference com.flipcash.shared.* directly.
180+
implementation(project(":kmp:shared-core"))
178181
implementation(project(":services:flipcash-compose"))
179182

180183
implementation(project(":apps:flipcash:core"))

‎build-logic/convention/build.gradle.kts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,9 @@ gradlePlugin {
4141
id = "flipcash.android.ed25519.shadow"
4242
implementationClass = "AndroidEd25519ShadowConventionPlugin"
4343
}
44+
register("kmpLibrary") {
45+
id = "flipcash.kmp.library"
46+
implementationClass = "KmpLibraryConventionPlugin"
47+
}
4448
}
4549
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import org.gradle.api.Plugin
2+
import org.gradle.api.Project
3+
4+
/**
5+
* Convention plugin for KMP library modules.
6+
*
7+
* Applies:
8+
* - `org.jetbrains.kotlin.multiplatform`
9+
* - `com.android.kotlin.multiplatform.library`
10+
*
11+
* After applying this plugin the `kotlin {}` DSL block is available for configuring targets,
12+
* source sets, and dependencies.
13+
*
14+
* Usage in a module's `build.gradle.kts`:
15+
* ```
16+
* plugins {
17+
* alias(libs.plugins.flipcash.kmp.library)
18+
* }
19+
* ```
20+
*/
21+
class KmpLibraryConventionPlugin : Plugin<Project> {
22+
override fun apply(target: Project) {
23+
with(target) {
24+
with(pluginManager) {
25+
apply("org.jetbrains.kotlin.multiplatform")
26+
apply("com.android.kotlin.multiplatform.library")
27+
}
28+
}
29+
}
30+
}

‎build.gradle.kts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ plugins {
3232
alias(libs.plugins.androidx.room) apply false
3333
alias(libs.plugins.screenshot) apply false
3434
alias(libs.plugins.kover)
35+
// KMP modules: shared-core umbrella + libs/* pilots
36+
alias(libs.plugins.kotlin.multiplatform) apply false
37+
alias(libs.plugins.android.kotlin.multiplatform.library) apply false
38+
alias(libs.plugins.kmmbridge) apply false
3539
}
3640

3741
// NOTE: The per-project `allprojects { }` configuration that used to live here

‎gradle.properties‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,5 @@ android.enableR8.fullMode=true
4848

4949
# Enabled parallel sync for Gradle 9.4+
5050
org.gradle.tooling.parallel=true
51+
52+
kotlin.native.ignoreDisabledTargets=true

‎gradle/libs.versions.toml‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ android-targetSdk = "37"
55
android-java = "21"
66

77
kotlin = "2.4.10"
8-
ksp = "2.3.11"
8+
ksp = "2.3.10"
99
kotlinx-coroutines = "1.11.0"
1010
kotlinx-serialization = "1.11.0"
1111
kotlinx-datetime = "0.8.0"
1212

1313
kover = "0.9.9"
1414
agp = "9.3.1"
15+
kmmbridge = "1.2.1"
1516
google-services = "4.5.0"
1617

1718
androidx-appcompat = "1.7.1"
@@ -48,26 +49,26 @@ hilt-jetpack = "1.4.0"
4849
okhttp = "5.4.0"
4950
retrofit = "3.0.0"
5051
kin-sdk = "2.1.2"
51-
grpc-android = "1.83.1"
52+
grpc-android = "1.83.0"
5253
slf4j = "1.7.36"
53-
firebase-bom = "34.17.0"
54+
firebase-bom = "34.16.0"
5455
play-service-ml-barcode = "18.3.1"
5556
play-services-auth-api-phone = "18.3.1"
5657
google-play-billing = "9.1.0"
5758
google-play-updates = "2.1.0"
5859

59-
grpc = "1.83.1"
60-
grpc-okhttp = "1.83.1"
60+
grpc = "1.83.0"
61+
grpc-okhttp = "1.83.0"
6162
grpc-kotlin = "1.5.0"
6263
protobuf = "4.35.1"
6364
protobuf-plugin = "0.10.0"
6465
protovalidate-kt = "0.1.1"
6566

66-
lib-phone-number-port = "9.0.36"
67-
lib-phone-number-google = "9.0.36"
67+
lib-phone-number-port = "9.0.34"
68+
lib-phone-number-google = "9.0.35"
6869
zxing = "3.5.4"
6970

70-
androidx-benchmark-macro = "1.5.0-beta01"
71+
androidx-benchmark-macro = "1.5.0-alpha07"
7172
androidx-profileinstaller = "1.4.1"
7273
androidx-test-runner = "1.7.0"
7374
junit = "4.13.2"
@@ -325,6 +326,7 @@ flipcash-android-library = { id = "flipcash.android.library" }
325326
flipcash-android-library-compose = { id = "flipcash.android.library.compose" }
326327
flipcash-android-feature = { id = "flipcash.android.feature" }
327328
flipcash-android-ed25519-shadow = { id = "flipcash.android.ed25519.shadow" }
329+
flipcash-kmp-library = { id = "flipcash.kmp.library" }
328330
android-application = { id = "com.android.application", version.ref = "agp" }
329331
android-library = { id = "com.android.library", version.ref = "agp" }
330332
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
@@ -344,3 +346,6 @@ androidx-baselineprofile = { id = "androidx.baselineprofile", version.ref = "and
344346
screenshot = { id = "com.android.compose.screenshot", version.ref = "screenshot" }
345347
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
346348
protobuf-validate = { id = "dev.bmcreations.protovalidate", version.ref = "protovalidate-kt" }
349+
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
350+
android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
351+
kmmbridge = { id = "co.touchlab.kmmbridge.github", version.ref = "kmmbridge" }

‎kmp/shared-core/build.gradle.kts‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
plugins {
2+
kotlin("multiplatform")
3+
id("com.android.kotlin.multiplatform.library")
4+
id("co.touchlab.kmmbridge.github") version "1.2.1"
5+
`maven-publish`
6+
}
7+
8+
group = "com.flipcash"
9+
version = "0.1.0"
10+
11+
kotlin {
12+
android {
13+
namespace = "com.flipcash.shared"
14+
compileSdk = 37
15+
minSdk = 29
16+
}
17+
18+
val appleTargets = listOf(iosArm64(), iosSimulatorArm64(), iosX64())
19+
appleTargets.forEach {
20+
it.binaries.framework {
21+
baseName = "SharedCore"
22+
isStatic = true
23+
export(project(":libs:encryption:base58"))
24+
}
25+
}
26+
27+
sourceSets {
28+
commonMain {
29+
dependencies {
30+
api(project(":libs:encryption:base58"))
31+
}
32+
}
33+
}
34+
}
35+
36+
kmmbridge {
37+
gitHubReleaseArtifacts()
38+
spm(swiftToolVersion = "5.9") {
39+
iOS { v("15") }
40+
}
41+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.flipcash.shared
2+
3+
/**
4+
* Marker for the cross-platform shared core. Gives iOS a symbol to verify the
5+
* XCFramework is linked (`SharedCore.version`) and a home for the shared surface
6+
* as it grows across milestones.
7+
*/
8+
object SharedCore {
9+
const val version: String = "0.1.0"
10+
}
Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
11
plugins {
2-
alias(libs.plugins.flipcash.android.library)
2+
kotlin("multiplatform")
3+
id("com.android.kotlin.multiplatform.library")
34
}
45

5-
android {
6-
namespace = "${Gradle.codeNamespace}.encryption.base58"
7-
}
6+
kotlin {
7+
android {
8+
namespace = "com.getcode.encryption.base58"
9+
compileSdk = 37
10+
minSdk = 29
11+
withHostTest {}
12+
}
13+
14+
iosArm64()
15+
iosSimulatorArm64()
16+
iosX64()
817

9-
dependencies {
10-
testImplementation(kotlin("test"))
11-
testImplementation(libs.kotlinx.serialization.json) // parse cross-platform test-vector fixtures
18+
sourceSets {
19+
commonMain {
20+
// Pure Kotlin -- no external dependencies needed.
21+
}
22+
androidMain {
23+
// MessageDigest + BigInteger -- JDK only; no extra Gradle deps.
24+
}
25+
commonTest {
26+
dependencies {
27+
implementation(kotlin("test"))
28+
implementation(libs.kotlinx.serialization.json)
29+
}
30+
}
31+
}
1232
}

0 commit comments

Comments
 (0)