Petra Barus
Petra Barus

Reputation: 4013

Cannot create and build Kotlin Multiplatform Shared Module in existing Android codebase

I am trying to follow this tutorial for Android application works on iOS using Kotlin Multiplatform.

https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-integrate-in-existing-app.html#make-your-code-cross-platform

Basically my goal is to reuse the business logic Kotlin code in existing Android code so our team can experiment on new iPhone user base.

However after I tried the step for adding new Kotlin Multiplatform Shared Module. It cannot compile.

The error is

Unresolved reference: libs

I tried comparing with the source code they provided.

https://github.com/Kotlin/kmm-integration-sample/tree/final

It seems that the Android Studio version and/or the Gradle version of the sample code is outdated.

My code of shared/build.gradle.kts is below

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
}

kotlin {
    androidTarget {
        compilations.all {
            kotlinOptions {
                jvmTarget = "1.8"
            }
        }
    }
    
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach {
        it.binaries.framework {
            baseName = "shared"
            isStatic = true
        }
    }

    sourceSets {
        commonMain.dependencies {
            //put your multiplatform dependencies here
        }
        commonTest.dependencies {
            implementation(libs.kotlin.test)
        }
    }
}

android {
    namespace = "net.petrabarus.poc.android.shared"
    compileSdk = 34
    defaultConfig {
        minSdk = 24
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

while the code of shared/build.gradle.kts in the sample code is below.

plugins {
    kotlin("multiplatform")
    id("com.android.library")
}

kotlin {
    android()
    
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach {
        it.binaries.framework {
            baseName = "shared"
        }
    }

    sourceSets {
        val commonMain by getting
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test"))
            }
        }
        val androidMain by getting
        val androidTest by getting
        val iosX64Main by getting
        val iosArm64Main by getting
        val iosSimulatorArm64Main by getting
        val iosMain by creating {
            dependsOn(commonMain)
            iosX64Main.dependsOn(this)
            iosArm64Main.dependsOn(this)
            iosSimulatorArm64Main.dependsOn(this)
        }
        val iosX64Test by getting
        val iosArm64Test by getting
        val iosSimulatorArm64Test by getting
        val iosTest by creating {
            dependsOn(commonTest)
            iosX64Test.dependsOn(this)
            iosArm64Test.dependsOn(this)
            iosSimulatorArm64Test.dependsOn(this)
        }
    }
}

android {
    compileSdk = 31
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdk = 21
        targetSdk = 31
    }
}

It seems that the newest one uses the shared dependency configuration from Gradle.

https://docs.gradle.org/current/userguide/platforms.html

I added this libs.versions.toml below from the KMM Project Wizard

https://kmp.jetbrains.com/

[versions]
agp = "8.2.0"
kotlin = "1.9.22"

[plugins]
androidLibrary = { id = "com.android.library", version.ref = "agp" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }

The error is now like below


Error resolving plugin [id: 'org.jetbrains.kotlin.multiplatform', version: '1.9.22']
> The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version, so compatibility cannot be checked.

This is the code

https://github.com/petrabarus/poc-android-export-kmm-module-to-maven/tree/add-shared

What did I do wrong, and how do I fix this?

The Android Studio I am using is below

Android Studio Hedgehog | 2023.1.1
Build #AI-231.9392.1.2311.11076708, built on November 9, 2023
Runtime version: 17.0.7+0-17.0.7b1000.6-10550314 aarch64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
macOS 14.2.1
GC: G1 Young Generation, G1 Old Generation
Memory: 1024M
Cores: 8
Metal Rendering is ON
Registry:
    external.system.auto.import.disabled=true
    ide.text.editor.with.preview.show.floating.toolbar=false

Non-Bundled Plugins:
    com.jetbrains.kmm (0.8.2(231)-25)
    org.jetbrains.compose.desktop.ide (1.6.0)

Upvotes: 1

Views: 846

Answers (1)

Petra Barus
Petra Barus

Reputation: 4013

I tried to match the dependencies and version of the libraries from the shared/build.gradle.kts, root build.gradle.kts and libs.versions.toml

// gradle/libs.versions.toml
[versions]
agp = "8.2.0"
kotlin = "1.9.0"

[plugins]
androidLibrary = { id = "com.android.library", version.ref = "agp" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
//build.gradle.kts
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id("com.android.library") version "8.2.0" apply false
    id("com.android.application") version "8.2.0" apply false
    id("org.jetbrains.kotlin.android") version "1.9.0" apply false
    id("org.jetbrains.kotlin.multiplatform") version "1.9.0" apply false
}

Now the error change to

Build was configured to prefer settings repositories over project repositories but repository 'ivy' was added by build file 'shared/build.gradle.kts'

The problem is in these lines

    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach {
        it.binaries.framework {
            baseName = "shared"
            isStatic = true
        }
    }

Finally I tried matching the settings.gradle.kts with the KMM Project Wizard.

Previous is

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

Now is

pluginManagement {
    repositories {
        maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    //repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
    }
}

The build runs! I am not sure why, but it runs!

Upvotes: 0

Related Questions