huh, as soon as i add `ios()` to my common gradle ...
# multiplatform
a
huh, as soon as i add
ios()
to my common gradle file, it starts failing to resolve my dependencies:
Copy code
Could not resolve org.jetbrains.compose.foundation:foundation:1.1.0.
Required by:
    project :common
Copy code
import org.jetbrains.compose.compose

plugins {
    kotlin("multiplatform")
    id("org.jetbrains.compose")
    id("com.android.library")
    id("kotlin-parcelize")
}

group = "com.darkrockstudios.apps.hammer"
version = "1.0-SNAPSHOT"

kotlin {
    android()
    jvm("desktop") {
        compilations.all {
            kotlinOptions.jvmTarget = "11"
        }
    }
    ios {
        binaries {
            framework {
                baseName = "common"
            }
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(compose.runtime)
                implementation(compose.foundation)
                implementation(compose.material)
                api("com.arkivanov.decompose:decompose:0.6.0")
                implementation("com.arkivanov.decompose:extensions-compose-jetbrains:0.6.0")
                api("io.github.aakira:napier:2.6.1")
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test"))
            }
        }
        val androidMain by getting {
            dependencies {
                api("androidx.appcompat:appcompat:1.4.2")
                api("androidx.core:core-ktx:1.8.0")
                api("com.arkivanov.decompose:extensions-compose-jetbrains:0.6.0")
            }
        }
        val iosMain by getting
        val iosTest by getting
        val androidTest by getting {
            dependencies {
                implementation("junit:junit:4.13.2")
            }
        }
        val desktopMain by getting {
            dependencies {
                api(compose.preview)
                api("com.arkivanov.decompose:extensions-compose-jetbrains:0.6.0")
            }
        }
        val desktopTest by getting
    }
}

android {
    compileSdk = 31
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdk = 24
        targetSdk = 31
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}
you need to go up to the 1.2 alphas for native ios
a
ooo
now... okay so i actually want swift UI for ios, so i guess i need to restructure my modules so compose is not attempting to be included in the iOS target
huh, never done this before, but I guess I need to add a new "compose" source set that only the compose targets will use?
or would it be a totally different module...
e
you can add a new hierarchical source set, or create a new module, that only specific source sets depend on; either way can work
actually nevermind; https://kotlinlang.org/docs/multiplatform-share-on-platforms.html#configure-the-hierarchical-structure-manually says
Kotlin doesn't currently support sharing a source set for these combinations:
• Several JVM targets
• JVM + Android targets
so that pretty much rules out any possible application of hierarchy…
a
huh
so...
how do people do this lol
the Decompose sample apps live inside a larger project, to its a bit hard to see how that structure would apply to just a single app, without the larget library project
what am i missing, i figured adding this to the source sets block would allow me to define a new arbitrary source set:
Copy code
val composeUi by getting {
            dependencies {
                api(compose.runtime)
                api(compose.foundation)
                api(compose.material)
                api("com.arkivanov.decompose:extensions-compose-jetbrains:0.6.0")
            }
        }
e
if you want to create a new source set, use
creating
instead of
getting
. then you want to
jvmMain { dependsOn(composeUi) }
but what I mentioned is that apparently
jvmMain { dependsOn(composeUi) }; androidMain { dependsOn(composeUi) }
isn't supported, which for now means there's not really any point to doing this. either you only support one JVM-like platform, in which case just put Compose dependencies on that platform only, or you support multiple, in which case you need a new module
a
got ya
okay, so new module it is
hey here's a question, where does the sourceSet
commonMain
come from? When in create a new module with a name like
composeUi
it doesn't recognize a source set:
composeUiMain
a
You can just disable the Compose plugin for native in your module. See the thread - https://kotlinlang.slack.com/archives/C01D6HTPATV/p1651705701259909?thread_ts=1651705701.259909&cid=C01D6HTPATV
e
each compilation creates
${name}Main
and
${name}Test
source sets by default, so if you did
Copy code
kotlin {
    jvm {
        compilations.create("composeUi")
then you'd have
composeUiMain
and
composeUiTest
source sets. but I don't think that's what you want
a
ya
I'm going with another module approach, having some issues w\ it's own dependencies though, so close...
I've added the dependencies every which way, but my
main
source set still doesn't see the compose classes:
Copy code
val kotlin_version: String by extra
plugins {
    kotlin("multiplatform")
    id("org.jetbrains.compose")
    id("com.android.library")
    id("kotlin-parcelize")
}

group = "com.darkrockstudios.apps.hammer.composeui"
version = "1.0-SNAPSHOT"

kotlin {
    android()
    jvm {
        compilations.all {
            kotlinOptions.jvmTarget = "11"
        }
    }

    sourceSets {
        val jvmMain by getting {
            dependencies {
                api(project(":common"))
                api(compose.runtime)
                api(compose.foundation)
                api(compose.material)
                api("com.arkivanov.decompose:extensions-compose-jetbrains:0.6.0")
            }
        }
    }

    dependencies {
        api(project(":common"))
        api(compose.runtime)
        api(compose.foundation)
        api(compose.material)
        api("com.arkivanov.decompose:extensions-compose-jetbrains:0.6.0")
    }
}
android {
    compileSdk = 31
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdk = 24
        targetSdk = 31
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}

dependencies {
    api(project(":common"))
    api(compose.runtime)
    api(compose.foundation)
    api(compose.material)
    api("com.arkivanov.decompose:extensions-compose-jetbrains:0.6.0")
}
repositories {
    mavenCentral()
}
@Arkadii Ivanov do you put that in your common gradle?
a
Do you want a separate module for Compose UI shared for desktop and android?
e
you need a separate module if you want to share code between desktop and android without affecting a native sourceset in the same mpp project 😕
a
yes im going the shared module route
e
your common dependencies are in the wrong place, they need to be in
Copy code
kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
a
I just figured it out. so in multiplatform modules,
commonMain
is a special source set, My previous mp module was CALLED
common
so I thought
commonMain
was named so b/c of the module...
so in my composeUi module, i was trying
composeUiMain
and various things...
with that disable compiler snippet? ya, i wish i had seen that a few hours ago, im fairly far down this road now 😛
a
But a separate module with Compose UI works better. See the example - https://github.com/JetBrains/compose-jb/tree/master/examples/todoapp/common/compose-ui
e
you can't put composefoundation1.1 in commonMain dependencies if you have a native target, regardless of plugin
a
ya thats what im doing now, then the swift UI can just live in the ios module i suppose
a
There are workarounds. I have this setup working in my app
So there are two options. 1. A single module with android/desktop/iOS in commonMain, and compose UI in javaMain. 2. Shared module with android/JVM/iOS in commonMain, and no compose. Plus a separate module with Compose only android/JVM, which depends on the shared module. https://github.com/JetBrains/compose-jb/tree/master/examples/todoapp/common/compose-ui I recommend the 2nd option
a
I'm going to give a ted talk on setting up a multiplatform project when im done here...
a
You can just follow the official todoapp sample. It shows exactly your use case. A shared module between all targets. Compose UI module for Android/desktop. And an iOS app with SwiftUI. There is also a web app with Compose for web.
a
lies! no idk, i just keep trying by going File -> New Project, but it appears those templates are perpetually out of date
a
Tbh, I never use File -> New project. I just create folders manually and copy Gradle files from other projects 😀
2
a
😛
the problem im running into now is that the android module says it has no compose compiler... took a look at that todo app, it looks like it's using some 3rd party multiplatform-compose-setup, that might be what is fixing thing
before moving to my composeUi module though, this Android module built & ran, and i can't quite see what is different now
a
a
ah look at that
oh its quite simple under the hood, nice