Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly opt-in to Experimental APIs in Kotlin Multiplatform + Compose?

I’m working on a Kotlin Multiplatform + Compose Multiplatform project and trying to opt-in to ExperimentalMaterial3Api.

In my build.gradle.kts, I added:

sourceSets.all {
    languageSettings.optIn("androidx.compose.material3.ExperimentalMaterial3Api")
}

But this gives errors for each platform (Android, iOS, etc.), saying the annotation is unresolved or not recognized.

Compose Multiplatform plugin: 1.9.0-beta03

Material3 version: 1.9.0-beta03

Is there a correct way to apply ExperimentalMaterial3Api opt-in across all source sets in a KMM + CMP project?

build.gradle.kts

import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
// Desktop and WASM imports commented out
//import org.jetbrains.compose.desktop.application.dsl.TargetFormat
//import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
//import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.composeMultiplatform)
    alias(libs.plugins.composeCompiler)
    alias(libs.plugins.composeHotReload)
    alias(libs.plugins.kotlinSerialization)
    alias(libs.plugins.kmpGrpcPlugin)
}

kotlin {

    applyDefaultHierarchyTemplate()

    androidTarget {
        @OptIn(ExperimentalKotlinGradlePluginApi::class)
        compilerOptions {
            jvmTarget.set(JvmTarget.JVM_21)
        }
    }

    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "ComposeApp"
            isStatic = true
        }
    }

    // Desktop target commented out
    //jvm("desktop")

    // WASM target commented out
    /*
    @OptIn(ExperimentalWasmDsl::class)
    wasmJs {
        outputModuleName.set("composeApp")
        browser {
            val rootDirPath = project.rootDir.path
            val projectDirPath = project.projectDir.path
            commonWebpackConfig {
                outputFileName = "composeApp.js"
                devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
                    static = (static ?: mutableListOf()).apply {
                        // Serve sources to debug inside browser
                        add(rootDirPath)
                        add(projectDirPath)
                    }
                }
            }
        }
        binaries.executable()
    }
    */

    sourceSets.all {
        languageSettings.optIn("androidx.compose.material3.ExperimentalMaterial3Api")
    }

    sourceSets {
        // Desktop sourceSet commented out
        //val desktopMain by getting

        androidMain.dependencies {
            implementation(compose.preview)
            implementation(libs.koin.core.coroutines)
            implementation(libs.androidx.activity.compose)
            implementation(libs.grpc.okhttp)
        }
        commonMain.dependencies {
            implementation(libs.compottie)
            implementation(compose.runtime)
            implementation(compose.foundation)
            implementation(compose.material3)
            implementation(libs.adaptive)
            implementation(compose.materialIconsExtended)
            implementation(compose.ui)
            implementation(libs.kotlinx.serialization.json)
            implementation(libs.navigation.compose)
            implementation(libs.material3)
            implementation(compose.components.resources)
            implementation(compose.components.uiToolingPreview)
            implementation(libs.androidx.lifecycle.viewmodel)
            implementation(libs.androidx.lifecycle.runtimeCompose)
            implementation(project.dependencies.platform(libs.koin.bom))
            implementation(libs.koin.core)
            implementation(libs.koin.compose)
            implementation(libs.koin.compose.viewmodel)
            implementation(libs.koin.compose.viewmodel.navigation)
            api(libs.kotlinx.coroutines.core)
        }
        commonTest.dependencies {
            implementation(libs.kotlin.test)
        }
        // Desktop dependencies commented out
        /*
        desktopMain.dependencies {
            implementation(compose.desktop.currentOs)
            implementation(libs.kotlinx.coroutinesSwing)
        }
        */
    }
}

android {
    namespace = "abc.abc.abc.app"
    compileSdk = libs.versions.android.compileSdk.get().toInt()

    defaultConfig {
        applicationId = "abc.abc.abc.app"
        minSdk = libs.versions.android.minSdk.get().toInt()
        targetSdk = libs.versions.android.targetSdk.get().toInt()
        versionCode = 1
        versionName = "1.0"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_21
        targetCompatibility = JavaVersion.VERSION_21
    }
}

dependencies {
    debugImplementation(compose.uiTooling)
}

// Desktop compose configuration commented out
/*
compose.desktop {
    application {
        mainClass = "abc.abc.abc.app.MainKt"

        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "abc.abc.abc.app"
            packageVersion = "1.0.0"
        }
    }
}
*/

kmpGrpc {
    common()
    android()
    native()
    // Desktop and JS targets commented out
    //jvm()
    //js()

    includeWellKnownTypes = true

    protoSourceFolders = project.files("../../protos")
}
like image 485
Vivek Modi Avatar asked Nov 14 '25 15:11

Vivek Modi


1 Answers

Correct place is kotlin.compilerOptions.optIn:

kotlin {
  compilerOptions {
    optIn.add("androidx.compose.material3.ExperimentalMaterial3Api")
  }
}
like image 166
Jan Bína Avatar answered Nov 17 '25 09:11

Jan Bína