KMPCharts/.paul/phases/v0.3.0-ios-build-plan.md
Trentin Davide d6f51cdef2 feat(ios): iOS build pipeline + XCFramework, fix K/Native source bugs
Modules: chart-realtime (commonMain, iosMain), root, .paul

- chart-realtime/build.gradle.kts: applyDefaultHierarchyTemplate() + XCFramework("ChartRealtime") over iosX64/iosArm64/iosSimulatorArm64, baseName CamelCase
- commonMain RealtimeChartState/CircularBuffer: switch to kotlin.concurrent.Volatile, add kotlin.jvm.JvmName import (OptionalExpectation)
- commonMain AxisRenderer: replace JVM-only String.format with multiplatform formatFixed/formatScientific/pow10 helpers
- iosMain Platform.ios.kt: NSDate() + timeIntervalSinceReferenceDate + 978_307_200s 1970-epoch offset (K/Native binding has no direct timeIntervalSince1970)
- gradle.properties: remove Linux JDK pin (rely on JAVA_HOME)
- .paul: phases plan, STATE+ROADMAP updates

Acceptance: A1 compile 3 iOS targets, A2 linkDebugFrameworkIosSimulatorArm64, A3 iosSimulatorArm64Test (33 tests, 0 failures), A4 assembleChartRealtimeXCFramework (ios-arm64 + ios-arm64_x86_64-simulator slices), A5 Android assembleRelease/publishToMavenLocal --dry-run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 12:45:21 +02:00

4.9 KiB
Raw Permalink Blame History

v0.3.0 — iOS Build & Test Pipeline Plan

Goal

Wire chart-realtime for full iOS pipeline: compile all 3 iOS targets, link debug framework on iosSimulatorArm64, run commonTest on iOS sim, produce release XCFramework. Keep Android green. No new features, no demo app, no SPM/CocoaPods/CI.

Acceptance:

  • A1: ./gradlew :chart-realtime:compileKotlinIosX64 compileKotlinIosArm64 compileKotlinIosSimulatorArm64 green
  • A2: ./gradlew :chart-realtime:linkDebugFrameworkIosSimulatorArm64 green
  • A3: ./gradlew :chart-realtime:iosSimulatorArm64Test green, executes existing common tests
  • A4: ./gradlew :chart-realtime:assembleXCFramework produces chart-realtime/build/XCFrameworks/release/chart-realtime.xcframework
  • A5: ./gradlew :chart-realtime:assemble green (Android non-regression)

Locked decisions

  • T0: remove org.gradle.java.home pin (rely on JAVA_HOME)
  • XCFramework baseName: ChartRealtime (CamelCase iOS convention)
  • Include iosX64 target in XCFramework
  • Local Mac dev only, no CI

Tasks

T0 — Mac JDK / gradle.properties sanity

  • Goal: Unblock local Mac build. Current gradle.properties pins Linux JDK path. Pre-req for A1A5.
  • Files: gradle.properties
  • Agent: gradle-expert
  • Action: remove line org.gradle.java.home=/home/dtrentin/.local/share/JetBrains/Toolbox/apps/android-studio/jbr. Keep other lines unchanged.
  • Deps: none
  • Verify: ./gradlew :chart-realtime:help

T1+T2+T4 — Batched build.gradle.kts edit

  • Goal: iOS hierarchy explicit + XCFramework task.
  • Files: chart-realtime/build.gradle.kts
  • Agent: gradle-expert (single edit, single agent)
  • Actions:
    • Apply default hierarchy template explicitly (applyDefaultHierarchyTemplate())
    • Configure each iOS target with binaries.framework { baseName = "ChartRealtime"; xcf.add(this) } using XCFramework("ChartRealtime") helper from org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
    • Keep compose.material3 in commonMain (CMP 1.8.0 supports iOS native)
    • Do not break Android target, publishing, or existing source-set deps
  • Deps: T0
  • Verify:
    • ./gradlew :chart-realtime:compileKotlinIosX64
    • ./gradlew :chart-realtime:compileKotlinIosArm64
    • ./gradlew :chart-realtime:compileKotlinIosSimulatorArm64
    • ./gradlew :chart-realtime:linkDebugFrameworkIosSimulatorArm64
    • ./gradlew :chart-realtime:assembleXCFramework

T3 — iosTest wiring

  • Goal: iosTest source set runs existing commonTest files on iOS sim.
  • Files: chart-realtime/build.gradle.kts (only if hierarchy template doesn't auto-wire)
  • Agent: unit-test-writer
  • Inputs: existing commonTest.dependencies { implementation(libs.kotlin.test) }. Default hierarchy template wires iosTest → commonTest automatically. Verify; add explicit block only if test discovery fails.
  • Deps: T1+T2+T4
  • Verify: ./gradlew :chart-realtime:iosSimulatorArm64Test

T5 — Android non-regression guard

  • Goal: Confirm Android target/build/publish untouched.
  • Agent: android-build-resolver
  • Deps: T1+T2+T4
  • Verify: ./gradlew :chart-realtime:assembleRelease publishToMavenLocal --dry-run

T6 — Smoke acceptance run

  • Goal: Sequential run of all 5 acceptance commands.
  • Agent: general-purpose
  • Deps: T3, T5
  • Verify: all 5 commands green

Parallelism

Group Tasks
P0 T0
P1 T1+T2+T4 (one batched agent call)
P2 T3, T5 (parallel)
P3 T6
P4 Unify

Risks

  • R1: gradle.properties Linux JDK path — fixed in T0
  • R2: compose.material3 iOS native — supported in 1.8.0; fallback = isolate to non-iOS if compile fails
  • R3: Hierarchy template silent inactivity — applyDefaultHierarchyTemplate() made explicit
  • R4: commonTest not seen by iosTest — same hierarchy fix
  • R5: XCFramework name collision — single XCFramework("ChartRealtime") registration
  • R6: Compose link errors on iOS — defer to v0.4.0 if hit
  • R7: Android regression — T5 final gate, revert if needed
  • R8: Sim runtime requirement — confirmed installed (iPhone 17 family available)

New Deps

None. KGP + CMP 1.8.0 + Kotlin 2.1.0 cover everything.

Verification Commands

./gradlew :chart-realtime:help                                           # T0
./gradlew :chart-realtime:compileKotlinIosX64                            # A1
./gradlew :chart-realtime:compileKotlinIosArm64                          # A1
./gradlew :chart-realtime:compileKotlinIosSimulatorArm64                 # A1
./gradlew :chart-realtime:linkDebugFrameworkIosSimulatorArm64            # A2
./gradlew :chart-realtime:iosSimulatorArm64Test                          # A3
./gradlew :chart-realtime:assembleXCFramework                            # A4
ls chart-realtime/build/XCFrameworks/release/ChartRealtime.xcframework   # A4
./gradlew :chart-realtime:assembleRelease                                # A5
./gradlew :chart-realtime:publishToMavenLocal --dry-run                  # T5