I often program in Android Studio, however for my first KMP undertaking, I put in macOS in Docker within the docurr/macos undertaking, copied my undertaking to the macOS Paperwork folder, and developed it in Xcode. It is a easy undertaking (app.mercury) that opens a specified web site utilizing WebView.
It is a hyperlink to the undertaking repository
Then I attempted to construct my undertaking in Xcode, and I bought the error:
Did not construct cache for /Customers/panfstas/.gradle/caches/modules-2/files-2.1/org.jetbrains.compose.ui/ui-uikitx64/1.7.3/88a91f9a95d1f2922311c28d558b3f805424d289/ui.klib.
That is the construct log as an attachment as a result of it is rather lengthy
The log after the error above comprises the next line:
“Particulars: Inside error in physique decreasing: java.lang.StackOverflowError: null”
Than the primary information of the undertaking
gradle/libs.variations.toml
[versions]
agp = "9.2.1"
android-compileSdk = "36"
android-minSdk = "24"
android-targetSdk = "36"
androidx-activity = "1.13.0"
androidx-appcompat = "1.7.1"
androidx-core = "1.19.0"
androidx-espresso = "3.7.0"
#androidx-lifecycle = "2.11.0-beta01"
androidx-lifecycle = "2.8.4"
androidx-testExt = "1.3.0"
#composeMultiplatform = "1.11.1"
#composeWebviewMultiplatform = "2.0.1"
composeMultiplatform = "1.7.3"
composeWebviewMultiplatform = "1.9.40"
junit = "4.13.2"
kotlin = "2.4.0"
material3 = "1.11.0-alpha07"
[libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", model.ref = "kotlin" }
kotlin-testJunit = { module = "org.jetbrains.kotlin:kotlin-test-junit", model.ref = "kotlin" }
junit = { module = "junit:junit", model.ref = "junit" }
androidx-core-ktx = { module = "androidx.core:core-ktx", model.ref = "androidx-core" }
androidx-testExt-junit = { module = "androidx.take a look at.ext:junit", model.ref = "androidx-testExt" }
androidx-espresso-core = { module = "androidx.take a look at.espresso:espresso-core", model.ref = "androidx-espresso" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", model.ref = "androidx-appcompat" }
androidx-activity-compose = { module = "androidx.exercise:activity-compose", model.ref = "androidx-activity" }
compose-uiTooling = { module = "org.jetbrains.compose.ui:ui-tooling", model.ref = "composeMultiplatform" }
androidx-lifecycle-viewmodelCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", model.ref = "androidx-lifecycle" }
androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", model.ref = "androidx-lifecycle" }
compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", model.ref = "composeMultiplatform" }
compose-foundation = { module = "org.jetbrains.compose.basis:basis", model.ref = "composeMultiplatform" }
compose-material3 = { module = "org.jetbrains.compose.material3:material3", model.ref = "composeMultiplatform" }
compose-ui = { module = "org.jetbrains.compose.ui:ui", model.ref = "composeMultiplatform" }
compose-components-resources = { module = "org.jetbrains.compose.elements:components-resources", model.ref = "composeMultiplatform" }
compose-uiToolingPreview = { module = "org.jetbrains.compose.ui:ui-tooling-preview", model.ref = "composeMultiplatform" }
compose-webview-multiplatform = { module = "io.github.kevinnzou:compose-webview-multiplatform", model.ref = "composeWebviewMultiplatform"}
[plugins]
androidApplication = { id = "com.android.utility", model.ref = "agp" }
androidMultiplatformLibrary = { id = "com.android.kotlin.multiplatform.library", model.ref = "agp" }
composeMultiplatform = { id = "org.jetbrains.compose", model.ref = "composeMultiplatform" }
composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", model.ref = "kotlin" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", model.ref = "kotlin" }
gradle.properties
# Base Kotlin and Android settings
kotlin.code.type=official
android.nonTransitiveRClass=true
android.useAndroidX=true
# JDK 25
org.gradle.daemon.jvm.standards.model=25
kotlin.jvm.toolchain.launcher.enabled=false
kotlin.native.toolchain.enabled=false
org.gradle.java.installations.auto-download=true
org.gradle.java.installations.auto-detect=true
# Reminiscence and Metaspace
org.gradle.jvmargs=-Xmx1024m -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=2048m -Dfile.encoding=UTF-8
kotlin.daemon.jvmargs=-Xmx1024m
org.gradle.staff.max=1
kotlin.native.disableCompilerDaemon=false
# Cache
ompose.ios.uikit.cache.disabled=true
org.gradle.configuration-cache=false
org.gradle.caching=false
shared/construct.gradle.kts
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidMultiplatformLibrary)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
}
kotlin {
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "Shared"
isStatic = true
}
}
android {
namespace = "app.mercury.shared"
compileSdk = libs.variations.android.compileSdk.get().toInt()
minSdk = libs.variations.android.minSdk.get().toInt()
compilerOptions {
jvmTarget = JvmTarget.JVM_25
}
androidResources {
allow = true
}
withHostTest {
isIncludeAndroidResources = true
}
}
sourceSets {
androidMain.dependencies {
implementation(libs.compose.uiToolingPreview)
}
commonMain.dependencies {
implementation(libs.compose.runtime)
implementation(libs.compose.basis)
implementation(libs.compose.material3)
implementation(libs.compose.ui)
implementation(libs.compose.elements.assets)
implementation(libs.compose.webview.multiplatform)
implementation(libs.androidx.lifecycle.viewmodelCompose)
implementation(libs.androidx.lifecycle.runtimeCompose)
}
commonTest.dependencies {
implementation(libs.kotlin.take a look at)
}
}
}
dependencies {
androidRuntimeClasspath(libs.compose.uiTooling)
}
iosApp/iosApp/Data.plist
CADisableMinimumFrameDurationOnPhone
NSAppTransportSecurity
NSAllowsArbitraryLoads
On this module the primary WebView logic is applied.
shared/src/commonMain/kotlin/app/mercury/App.kt
package deal app.mercury
import androidx.compose.basis.structure.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.multiplatform.webview.internet.WebView
import com.multiplatform.webview.internet.rememberWebViewState
@Composable
enjoyable App() {
MaterialTheme {
val webViewState = rememberWebViewState("https://mercury-food-store.tilda.ws/")
WebView(
state = webViewState,
modifier = Modifier.fillMaxSize()
)
}
}
Command line to create a Docker container:
docker run
-it
--name macos-kmp-backend
-p 9006:8006
-p 4900:5900
--device /dev/kvm
--cap-add NET_ADMIN
--security-opt seccomp=unconfined
-e RAM_SIZE="15G"
-e CPU_CORES="4"
-v "C:UserspanfsAppDataLocalDockermacOStahoe:/storage"
--restart unless-stopped
dockurr/macos
