Is it possible to share Compose code between Deskt...
# compose-desktop
k
Is it possible to share Compose code between Desktop and Android? Examples?
k
I've looked at that. I'm having a real hard time with gradle. I can't seem to put the compose in the shared module so I tried a new one for just compose stuff
c
@kevindmoore I finally got it working in my project, so def possible but support in AS is super wonky if you're using AGP 7. Edit: You can see a simple example of it "breaking" in the IDE (even though it compiles fine) https://github.com/JetBrains/compose-jb/issues/1038 I'm happy to share snippets of my build.gradle.kts files if you want.
k
That would be great. Struggling with gradle. Seems like if it wasn't for Gradle, things would be much easier
💯 1
(I'm using AGP 7 too)
c
Okay, so I have a typical android app module with this line to depend on common
Copy code
implementation(project(":common-composables"))
common-composables build.gradle.kts
Copy code
import org.jetbrains.compose.compose

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

kotlin {
    android()
    jvm("desktop")

    sourceSets {
        named("commonMain") {
            dependencies {
                api(compose.runtime)
                api(compose.foundation)
                api(compose.animation)
                api(compose.ui)
                api(compose.uiTooling)
                api(compose.material)
                api(compose.materialIconsExtended)
                implementation(compose("org.jetbrains.compose.ui:ui-util"))
            }
        }
        named("androidMain") {
            dependencies {
                // Compose helpers
                implementation("com.google.accompanist:accompanist-insets:0.16.1")
                implementation("com.google.accompanist:accompanist-pager:0.16.1")
                implementation("com.google.accompanist:accompanist-pager-indicators:0.16.1")
            }
        }
    }
}

android {
    compileSdk = 30

    defaultConfig {
        minSdk = 24
        targetSdk = 30

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles("<http://consumer-rules.pro|consumer-rules.pro>")
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"), "<http://proguard-rules.pro|proguard-rules.pro>")
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    
    sourceSets {
        named("main") {
            manifest.srcFile("src/androidMain/AndroidManifest.xml")
            res.srcDirs("src/androidMain/res")
        }
    }
}
My root build.gradle has buildScript > dependencies with
Copy code
classpath("com.android.tools.build:gradle:7.1.0-alpha08") //AGP
classpath(kotlin("gradle-plugin", version = "1.5.21")) //KOTLIN
classpath("org.jetbrains.compose:compose-gradle-plugin:1.0.0-alpha3") //JB COMPOSE
then I have a desktop module with a kts of
Copy code
import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat

plugins {
    kotlin("multiplatform") // kotlin("jvm") doesn't work well in IDEA/AndroidStudio
    // (<https://github.com/JetBrains/compose-jb/issues/22>)
    id("org.jetbrains.compose")
}

kotlin {
    jvm { withJava() }
    sourceSets {
        named("jvmMain") {
            dependencies {
                implementation(compose.desktop.currentOs)
                implementation(project(":common-composables"))
            }
        }
    }
}

compose.desktop {
    application {
        mainClass = "MainKt"

        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "KotlinMultiplatformComposeDesktopApplication"
            packageVersion = "1.0.0"
        }
    }
}
With that I have a single shared composable and its accessible from Android and desktop modules!
k
Nice. Pretty similar to what I have. A couple of questions:
Copy code
1. Why jvm { withJava() }
2. It seems that jvm ("desktop") does something special as not having it breaks things
3. I think there are some pre-defined source set names that are important: commonMain, commonAndroid etc. Not sure about the jvm ones
c
Yeah. Those are all questions for some of the JB folks maybe. i just tried and failed for a few days until something worked.
k
That is I have done. Seems like trial and error
a
If you are new to multiplatform , try IntelliJ IDEA which comes with multiplatform project templates. No need for "try and error" 😉
c
Intellij idea won't open projects built with AGP 7+
k
Also, I found that the project that Intellij built had some problems
c
File a bug! I'll thumbs it up!
i
Why jvm { withJava() }
Not sure yet, but probably it isn't needed, if your code doesn't have
java
files.
It seems that jvm ("desktop") does something special
Yes, this line defines jvm target with a name
desktop
. Without it, Gradle don't know that it needs to compile sources in
desktopMain
folder
think there are some pre-defined source set names that are important:
For MPP project there is only one predefined source set - commonMain, the other ones you define explicitly:
Copy code
android()  // define android target, main source set is androidMain, test source set is androidTest, instrumental test source set is androidAndroidTest :)
jvm("desktop")  // define jvm target, main source set is desktopMain, test source set is desktopTest
💯 3
c
That's super helpful. thanks @Igor Demin
a
Have anybody managed to build a compose desktop app with a java file and a kmm shared lib? I still can't find the solution https://kotlinlang.slack.com/archives/C01D6HTPATV/p1628257318170400?thread_ts=1628257318.170400&amp;cid=C01D6HTPATV
k
I saw
Copy code
jvm { useJava() }