From e02972e1bed005f51bacda297b3dc117f0a35e20 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 25 May 2026 00:13:13 +0000 Subject: [PATCH] build(commons): enable iosArm64 + iosSimulatorArm64 targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2 task 10 of the iOS plan — flip on iOS targets for :commons. Gradle dep resolution is fully green for iOS; actual Kotlin/Native compilation runs on the macOS CI job (the dev container in which this was authored can't extract the K/N LLVM toolchain). Dep reshuffle to match what's actually KMP-available: - commonMain: kept project(":quartz"), Compose Multiplatform, coil-compose, androidx-collection, kotlinx-collections-immutable, kotlinx-serialization-json, compose components-resources, androidx-lifecycle-viewmodel, androidx-lifecycle-runtime-compose. These all publish iosArm64 + iosSimulatorArm64 variants per `.module` inspection. - jvmAndroid (NEW location): project(":nestsClient") (JVM+Android-only), coil-okhttp (JVM-only), markdown-commonmark / markdown-ui / markdown-ui-material3 (the RenderMarkdown.kt consumer is already in jvmAndroid), and androidx-lifecycle-viewmodel-compose (AndroidX publishes android + jvmStubs + linuxx64Stubs variants — no iOS, so the viewModel() Composable helper stays JVM-bound until we either swap to the org.jetbrains.androidx.lifecycle variant or accept a platform-specific ViewModel access pattern on iOS). - libs.versions.toml: adds androidx-lifecycle-viewmodel catalog entry. - New intermediate source set iosMain → both iosArm64Main and iosSimulatorArm64Main depend on it (clean place for iOS-only actuals when KmpLock, WeakReference, etc. get their iOS implementations). - .github/workflows/build.yml: test-quartz-ios job now also runs :commons:compileKotlinIosArm64 + :commons:compileKotlinIosSimulatorArm64. --- .github/workflows/build.yml | 12 +++++++ commons/build.gradle.kts | 62 ++++++++++++++++++++++++++++--------- gradle/libs.versions.toml | 1 + 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3ecb2b3e0..d9ed078f30 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -226,6 +226,18 @@ jobs: :quartz:iosSimulatorArm64Test \ :quartz:compileTestKotlinIosArm64 + # :commons gained iosArm64 + iosSimulatorArm64 targets in Phase 2 of the + # iOS plan. Compile-only for now — actual UI / lifecycle wiring will + # land with the iosApp module in Phase 3. The container that runs Claude + # Code can't extract the Kotlin/Native LLVM toolchain (sandbox limit), + # so this is the first place commonMain Compose code is actually + # type-checked against an Apple Native frontend. + - name: Compile Commons for iOS + run: | + ./gradlew \ + :commons:compileKotlinIosSimulatorArm64 \ + :commons:compileKotlinIosArm64 + - name: Upload iOS Test Reports uses: actions/upload-artifact@v7 if: failure() diff --git a/commons/build.gradle.kts b/commons/build.gradle.kts index 684213eea6..1205ae2ad9 100644 --- a/commons/build.gradle.kts +++ b/commons/build.gradle.kts @@ -44,15 +44,16 @@ kotlin { } } + // iOS targets — Phase 2 spike. Compile-only for now (no framework binary + // configured yet). Reveals which transitive deps need iOS variants and + // which commonMain files still reach for platform-only APIs. + iosArm64() + iosSimulatorArm64() + sourceSets { commonMain { dependencies { implementation(project(":quartz")) - // Audio-rooms ViewModel needs the listener orchestration + audio - // pipeline types (NestsListener, AudioRoomPlayer, AudioPlayer - // interface). Concrete OkHttp/Quic/MediaCodec/AudioTrack actuals - // stay in :nestsClient's platform source sets. - implementation(project(":nestsClient")) // Compose Multiplatform implementation(libs.jetbrains.compose.ui) @@ -61,13 +62,17 @@ kotlin { implementation(libs.jetbrains.compose.material3) implementation(libs.jetbrains.compose.ui.tooling.preview) - // Lifecycle ViewModel (KMP since 2.8.0) - implementation(libs.androidx.lifecycle.viewmodel.compose) + // Lifecycle (KMP since 2.8.0). lifecycle-viewmodel and + // lifecycle-runtime-compose ship iOS variants; + // lifecycle-viewmodel-compose (the viewModel() Composable + // helper) is Android-only and lives in jvmAndroid below. + implementation(libs.androidx.lifecycle.viewmodel) implementation(libs.androidx.lifecycle.runtime.compose) - // Image loading (Coil 3 - KMP) + // Image loading (Coil 3 - KMP). The okhttp network fetcher is + // JVM-only and lives in jvmAndroid; iOS will pull coil-ktor + // when that target wires its actual. implementation(libs.coil.compose) - implementation(libs.coil.okhttp) // LruCache (KMP-ready) implementation(libs.androidx.collection) @@ -81,11 +86,6 @@ kotlin { // Compose Multiplatform Resources implementation(libs.jetbrains.compose.components.resources) - - // Markdown rendering (richtext-commonmark) - implementation(libs.markdown.commonmark) - implementation(libs.markdown.ui) - implementation(libs.markdown.ui.material3) } } @@ -101,6 +101,32 @@ kotlin { create("jvmAndroid") { dependsOn(commonMain.get()) dependencies { + // Audio-rooms ViewModel needs the listener orchestration + + // audio pipeline types (NestsListener, AudioRoomPlayer, + // AudioPlayer interface). The :nestsClient module is + // jvmAndroid-only today (its QUIC + Opus + AudioRecord/Track + // stacks are JVM-bound), so the dep lives here, not in + // commonMain. iOS will need an audio-rooms reroute when + // Phase 5 lands. + implementation(project(":nestsClient")) + + // Coil's OkHttp network fetcher (JVM-only). iOS will use + // coil-ktor when the iOS Compose UI ships. + implementation(libs.coil.okhttp) + + // Markdown rendering (richtext-commonmark). The single + // consumer (RenderMarkdown.kt) already lives in jvmAndroid. + // iOS support pending Phase 3 markdown decision. + implementation(libs.markdown.commonmark) + implementation(libs.markdown.ui) + implementation(libs.markdown.ui.material3) + + // viewModel() Compose helper. AndroidX publishes this + // artifact for android/jvmStubs/linuxx64Stubs but not iOS, + // so it stays in jvmAndroid until we either swap to the + // org.jetbrains.androidx.lifecycle variant or accept a + // platform-specific ViewModel access pattern on iOS. + implementation(libs.androidx.lifecycle.viewmodel.compose) } } @@ -131,6 +157,14 @@ kotlin { } } + // iOS intermediate so iosArm64Main and iosSimulatorArm64Main share code. + val iosMain = + create("iosMain") { + dependsOn(commonMain.get()) + } + getByName("iosArm64Main").dependsOn(iosMain) + getByName("iosSimulatorArm64Main").dependsOn(iosMain) + getByName("androidHostTest") { dependencies { implementation(libs.junit) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 24ca396591..fff496a4cb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -109,6 +109,7 @@ androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "a androidx-junit-ktx = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "androidxJunit" } androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleRuntimeKtx" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } +androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "lifecycleRuntimeKtx" } androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-material3-windowSize = { group = "androidx.compose.material3", name = "material3-window-size-class" }