diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d77a706b37..433a7e4a35 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,12 +12,11 @@ updates: registries: "*" labels: [ "version update" ] groups: - kotlin-ksp-compose: + kotlin-ksp: patterns: - "org.jetbrains.kotlin:*" - "org.jetbrains.kotlin.jvm" - "com.google.devtools.ksp" - - "androidx.compose.compiler:compiler" open-pull-requests-limit: 10 registries: maven-google: diff --git a/.gitignore b/.gitignore index d4482596da..cc7ae83f73 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ _sandbox # Android Studio captures folder captures/ + +# Kotlin +.kotlin diff --git a/app-nia-catalog/dependencies/releaseRuntimeClasspath.txt b/app-nia-catalog/dependencies/releaseRuntimeClasspath.txt index 0b8b6d1cfe..b9135ed42b 100644 --- a/app-nia-catalog/dependencies/releaseRuntimeClasspath.txt +++ b/app-nia-catalog/dependencies/releaseRuntimeClasspath.txt @@ -109,10 +109,10 @@ io.coil-kt:coil-compose-base:2.6.0 io.coil-kt:coil-compose:2.6.0 io.coil-kt:coil:2.6.0 javax.inject:javax.inject:1 -org.jetbrains.kotlin:kotlin-stdlib-common:1.9.23 +org.jetbrains.kotlin:kotlin-stdlib-common:2.0.0 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 -org.jetbrains.kotlin:kotlin-stdlib:1.9.23 +org.jetbrains.kotlin:kotlin-stdlib:2.0.0 org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3 diff --git a/app/dependencies/prodReleaseRuntimeClasspath.txt b/app/dependencies/prodReleaseRuntimeClasspath.txt index 3c30d27e70..214ae5ca8f 100644 --- a/app/dependencies/prodReleaseRuntimeClasspath.txt +++ b/app/dependencies/prodReleaseRuntimeClasspath.txt @@ -206,10 +206,10 @@ io.coil-kt:coil-svg:2.6.0 io.coil-kt:coil:2.6.0 javax.inject:javax.inject:1 org.checkerframework:checker-qual:3.12.0 -org.jetbrains.kotlin:kotlin-stdlib-common:1.9.23 +org.jetbrains.kotlin:kotlin-stdlib-common:2.0.0 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 -org.jetbrains.kotlin:kotlin-stdlib:1.9.23 +org.jetbrains.kotlin:kotlin-stdlib:2.0.0 org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.0 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.0 diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index aa0e615ade..dc478a8298 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -14,6 +14,7 @@ * limitations under the License. */ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -28,15 +29,17 @@ java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } -tasks.withType().configureEach { - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() + +kotlin { + compilerOptions { + jvmTarget = JvmTarget.JVM_17 } } dependencies { compileOnly(libs.android.gradlePlugin) compileOnly(libs.android.tools.common) + compileOnly(libs.compose.gradlePlugin) compileOnly(libs.firebase.crashlytics.gradlePlugin) compileOnly(libs.firebase.performance.gradlePlugin) compileOnly(libs.kotlin.gradlePlugin) diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt index 3eeed97cf5..a8b1b17796 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt @@ -18,12 +18,14 @@ import com.android.build.api.dsl.ApplicationExtension import com.google.samples.apps.nowinandroid.configureAndroidCompose import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.getByType class AndroidApplicationComposeConventionPlugin : Plugin { override fun apply(target: Project) { with(target) { - pluginManager.apply("com.android.application") + apply(plugin = "com.android.application") + apply(plugin = "org.jetbrains.kotlin.plugin.compose") val extension = extensions.getByType() configureAndroidCompose(extension) diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt index dd9eead635..19fabf5494 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt @@ -18,14 +18,14 @@ import com.android.build.gradle.LibraryExtension import com.google.samples.apps.nowinandroid.configureAndroidCompose import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.getByType -import org.gradle.kotlin.dsl.kotlin class AndroidLibraryComposeConventionPlugin : Plugin { override fun apply(target: Project) { with(target) { - pluginManager.apply("com.android.library") + apply(plugin = "com.android.library") + apply(plugin = "org.jetbrains.kotlin.plugin.compose") val extension = extensions.getByType() configureAndroidCompose(extension) diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidCompose.kt index e38c5b3009..f16a8051a5 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidCompose.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidCompose.kt @@ -18,9 +18,11 @@ package com.google.samples.apps.nowinandroid import com.android.build.api.dsl.CommonExtension import org.gradle.api.Project +import org.gradle.api.provider.Provider +import org.gradle.kotlin.dsl.assign +import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.withType -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension /** * Configure Compose-specific options @@ -33,10 +35,6 @@ internal fun Project.configureAndroidCompose( compose = true } - composeOptions { - kotlinCompilerExtensionVersion = libs.findVersion("androidxComposeCompiler").get().toString() - } - dependencies { val bom = libs.findLibrary("androidx-compose-bom").get() add("implementation", platform(bom)) @@ -53,48 +51,22 @@ internal fun Project.configureAndroidCompose( } } - tasks.withType().configureEach { - kotlinOptions { - freeCompilerArgs += buildComposeMetricsParameters() - freeCompilerArgs += stabilityConfiguration() - freeCompilerArgs += strongSkippingConfiguration() - } - } -} + extensions.configure { + fun Provider.onlyIfTrue() = flatMap { provider { it.takeIf(String::toBoolean) } } + fun Provider<*>.relativeToRootProject(dir: String) = flatMap { + rootProject.layout.buildDirectory.dir(projectDir.toRelativeString(rootDir)) + }.map { it.dir(dir) } -private fun Project.buildComposeMetricsParameters(): List { - val metricParameters = mutableListOf() - val enableMetricsProvider = project.providers.gradleProperty("enableComposeCompilerMetrics") - val relativePath = projectDir.relativeTo(rootDir) - val buildDir = layout.buildDirectory.get().asFile - val enableMetrics = (enableMetricsProvider.orNull == "true") - if (enableMetrics) { - val metricsFolder = buildDir.resolve("compose-metrics").resolve(relativePath) - metricParameters.add("-P") - metricParameters.add( - "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + metricsFolder.absolutePath, - ) - } + project.providers.gradleProperty("enableComposeCompilerMetrics").onlyIfTrue() + .relativeToRootProject("compose-metrics") + .let(metricsDestination::set) - val enableReportsProvider = project.providers.gradleProperty("enableComposeCompilerReports") - val enableReports = (enableReportsProvider.orNull == "true") - if (enableReports) { - val reportsFolder = buildDir.resolve("compose-reports").resolve(relativePath) - metricParameters.add("-P") - metricParameters.add( - "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + reportsFolder.absolutePath - ) - } + project.providers.gradleProperty("enableComposeCompilerReports").onlyIfTrue() + .relativeToRootProject("compose-reports") + .let(reportsDestination::set) - return metricParameters.toList() + stabilityConfigurationFile = rootProject.layout.projectDirectory.file("compose_compiler_config.conf") + + enableStrongSkippingMode = true + } } - -private fun Project.stabilityConfiguration() = listOf( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=${project.rootDir.absolutePath}/compose_compiler_config.conf", -) - -private fun Project.strongSkippingConfiguration() = listOf( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:experimentalStrongSkipping=true", -) diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt index f9a6717c30..bfb7995958 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt @@ -20,11 +20,14 @@ import com.android.build.api.dsl.CommonExtension import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.kotlin.dsl.assign import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.provideDelegate -import org.gradle.kotlin.dsl.withType -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension /** * Configure base Kotlin with Android options @@ -48,7 +51,7 @@ internal fun Project.configureKotlinAndroid( } } - configureKotlin() + configureKotlin() dependencies { add("coreLibraryDesugaring", libs.findLibrary("android.desugarJdkLibs").get()) @@ -66,26 +69,26 @@ internal fun Project.configureKotlinJvm() { targetCompatibility = JavaVersion.VERSION_11 } - configureKotlin() + configureKotlin() } /** * Configure base Kotlin options */ -private fun Project.configureKotlin() { - // Use withType to workaround https://youtrack.jetbrains.com/issue/KT-55947 - tasks.withType().configureEach { - kotlinOptions { - // Set JVM target to 11 - jvmTarget = JavaVersion.VERSION_11.toString() - // Treat all Kotlin warnings as errors (disabled by default) - // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties - val warningsAsErrors: String? by project - allWarningsAsErrors = warningsAsErrors.toBoolean() - freeCompilerArgs = freeCompilerArgs + listOf( - // Enable experimental coroutines APIs, including Flow - "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", - ) - } +private inline fun Project.configureKotlin() = configure { + // Treat all Kotlin warnings as errors (disabled by default) + // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties + val warningsAsErrors: String? by project + when (this) { + is KotlinAndroidProjectExtension -> compilerOptions + is KotlinJvmProjectExtension -> compilerOptions + else -> TODO("Unsupported project extension $this ${T::class}") + }.apply { + jvmTarget = JvmTarget.JVM_11 + allWarningsAsErrors = warningsAsErrors.toBoolean() + freeCompilerArgs.add( + // Enable experimental coroutines APIs, including Flow + "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + ) } } diff --git a/build.gradle.kts b/build.gradle.kts index 38778e1007..dffc0c0dda 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,6 +36,7 @@ plugins { alias(libs.plugins.android.library) apply false alias(libs.plugins.android.test) apply false alias(libs.plugins.baselineprofile) apply false + alias(libs.plugins.compose) apply false alias(libs.plugins.kotlin.jvm) apply false alias(libs.plugins.kotlin.serialization) apply false alias(libs.plugins.dependencyGuard) apply false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 81a21426bd..e0b938e75a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,11 +43,11 @@ hilt = "2.51.1" hiltExt = "1.1.0" jacoco = "0.8.7" junit4 = "4.13.2" -kotlin = "1.9.23" +kotlin = "2.0.0" kotlinxCoroutines = "1.8.0" kotlinxDatetime = "0.5.0" kotlinxSerializationJson = "1.6.3" -ksp = "1.9.23-1.0.20" +ksp = "2.0.0-1.0.21" moduleGraph = "2.5.0" okhttp = "4.12.0" protobuf = "4.26.0" @@ -146,6 +146,7 @@ turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine # Dependencies of the included build-logic android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" } +compose-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" } firebase-crashlytics-gradlePlugin = { group = "com.google.firebase", name = "firebase-crashlytics-gradle", version.ref = "firebaseCrashlyticsPlugin" } firebase-performance-gradlePlugin = { group = "com.google.firebase", name = "perf-plugin", version.ref = "firebasePerfPlugin" } kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } @@ -157,6 +158,7 @@ android-application = { id = "com.android.application", version.ref = "androidGr android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } android-test = { id = "com.android.test", version.ref = "androidGradlePlugin" } baselineprofile = { id = "androidx.baselineprofile", version.ref = "androidxMacroBenchmark"} +compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } dependencyGuard = { id = "com.dropbox.dependency-guard", version.ref = "dependencyGuard" } firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlyticsPlugin" } firebase-perf = { id = "com.google.firebase.firebase-perf", version.ref = "firebasePerfPlugin" } diff --git a/lint/build.gradle.kts b/lint/build.gradle.kts index acb540c3b2..cfda9d64d6 100644 --- a/lint/build.gradle.kts +++ b/lint/build.gradle.kts @@ -14,6 +14,7 @@ * limitations under the License. */ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -29,9 +30,9 @@ java { targetCompatibility = JavaVersion.VERSION_11 } -tasks.withType().configureEach { - kotlinOptions { - jvmTarget = JavaVersion.VERSION_11.toString() +kotlin { + compilerOptions { + jvmTarget = JvmTarget.JVM_11 } }