From ddab9b642dc4dc7baf3dbe800a69afcd460a292f Mon Sep 17 00:00:00 2001 From: Antoine Jaury Date: Thu, 2 Jul 2026 18:29:07 +0200 Subject: [PATCH] new: introduce `build-logic` module to centralize Gradle configuration --- build-logic/build.gradle.kts | 13 +++++ build-logic/settings.gradle.kts | 20 ++++++++ .../main/kotlin/gwenedeg.compose.gradle.kts | 4 ++ .../kotlin/gwenedeg.kmp.library.gradle.kts | 48 +++++++++++++++++++ core/audioplayer/build.gradle.kts | 35 +------------- core/coroutines/build.gradle.kts | 35 +------------- core/logging/build.gradle.kts | 35 +------------- core/model/build.gradle.kts | 38 +-------------- data/records/build.gradle.kts | 35 +------------- data/resources/build.gradle.kts | 35 +------------- data/subtitle/build.gradle.kts | 35 +------------- gradle/libs.versions.toml | 6 +++ settings.gradle.kts | 1 + shared/build.gradle.kts | 37 ++------------ 14 files changed, 104 insertions(+), 273 deletions(-) create mode 100644 build-logic/build.gradle.kts create mode 100644 build-logic/settings.gradle.kts create mode 100644 build-logic/src/main/kotlin/gwenedeg.compose.gradle.kts create mode 100644 build-logic/src/main/kotlin/gwenedeg.kmp.library.gradle.kts diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts new file mode 100644 index 0000000..32e8373 --- /dev/null +++ b/build-logic/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + `kotlin-dsl` +} + +dependencies { + implementation(libs.android.gradlePlugin) + implementation(libs.kotlin.gradlePlugin) + implementation(libs.compose.gradlePlugin) + implementation(libs.composeCompiler.gradlePlugin) + // Makes the typed `libs` catalog accessors usable inside precompiled script plugins + // (workaround for https://github.com/gradle/gradle/issues/15383) + implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) +} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 0000000..53e4b62 --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,20 @@ +rootProject.name = "build-logic" + +dependencyResolutionManagement { + repositories { + google { + mavenContent { + includeGroupAndSubgroups("androidx") + includeGroupAndSubgroups("com.android") + includeGroupAndSubgroups("com.google") + } + } + mavenCentral() + gradlePluginPortal() + } + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} diff --git a/build-logic/src/main/kotlin/gwenedeg.compose.gradle.kts b/build-logic/src/main/kotlin/gwenedeg.compose.gradle.kts new file mode 100644 index 0000000..657cd4f --- /dev/null +++ b/build-logic/src/main/kotlin/gwenedeg.compose.gradle.kts @@ -0,0 +1,4 @@ +plugins { + id("org.jetbrains.compose") + id("org.jetbrains.kotlin.plugin.compose") +} diff --git a/build-logic/src/main/kotlin/gwenedeg.kmp.library.gradle.kts b/build-logic/src/main/kotlin/gwenedeg.kmp.library.gradle.kts new file mode 100644 index 0000000..f03d2ce --- /dev/null +++ b/build-logic/src/main/kotlin/gwenedeg.kmp.library.gradle.kts @@ -0,0 +1,48 @@ +import org.gradle.accessors.dm.LibrariesForLibs +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + id("org.jetbrains.kotlin.multiplatform") + id("com.android.kotlin.multiplatform.library") +} + +val libs = the() + +kotlin { + iosArm64() + iosSimulatorArm64() + + jvm() + + js { + browser() + } + + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + browser() + } + + androidLibrary { + // namespace is set per module in the consuming build file + compileSdk = + libs.versions.androidCompileSdk + .get() + .toInt() + minSdk = + libs.versions.androidMinSdk + .get() + .toInt() + + compilerOptions { + jvmTarget = JvmTarget.JVM_11 + } + } + + sourceSets { + commonTest.dependencies { + implementation(libs.kotlin.test) + } + } +} diff --git a/core/audioplayer/build.gradle.kts b/core/audioplayer/build.gradle.kts index c35877e..1edc84a 100644 --- a/core/audioplayer/build.gradle.kts +++ b/core/audioplayer/build.gradle.kts @@ -1,40 +1,10 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidMultiplatformLibrary) + id("gwenedeg.kmp.library") } kotlin { - iosArm64() - iosSimulatorArm64() - - jvm() - - js { - browser() - } - - @OptIn(ExperimentalWasmDsl::class) - wasmJs { - browser() - } - androidLibrary { namespace = "fr.ajaury.gwenedeg.core.audioplayer" - compileSdk = - libs.versions.androidCompileSdk - .get() - .toInt() - minSdk = - libs.versions.androidMinSdk - .get() - .toInt() - - compilerOptions { - jvmTarget = JvmTarget.JVM_11 - } } sourceSets { @@ -67,8 +37,5 @@ kotlin { // HTMLAudioElement interop on Wasm requires this opt-in. languageSettings.optIn("kotlin.js.ExperimentalWasmJsInterop") } - commonTest.dependencies { - implementation(libs.kotlin.test) - } } } diff --git a/core/coroutines/build.gradle.kts b/core/coroutines/build.gradle.kts index 1d86e26..e319b07 100644 --- a/core/coroutines/build.gradle.kts +++ b/core/coroutines/build.gradle.kts @@ -1,40 +1,10 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidMultiplatformLibrary) + id("gwenedeg.kmp.library") } kotlin { - iosArm64() - iosSimulatorArm64() - - jvm() - - js { - browser() - } - - @OptIn(ExperimentalWasmDsl::class) - wasmJs { - browser() - } - androidLibrary { namespace = "fr.ajaury.gwenedeg.core.coroutines" - compileSdk = - libs.versions.androidCompileSdk - .get() - .toInt() - minSdk = - libs.versions.androidMinSdk - .get() - .toInt() - - compilerOptions { - jvmTarget = JvmTarget.JVM_11 - } } sourceSets { @@ -46,8 +16,5 @@ kotlin { implementation(project.dependencies.platform(libs.koin.bom)) implementation(libs.koin.core) } - commonTest.dependencies { - implementation(libs.kotlin.test) - } } } diff --git a/core/logging/build.gradle.kts b/core/logging/build.gradle.kts index 0b46236..03625fc 100644 --- a/core/logging/build.gradle.kts +++ b/core/logging/build.gradle.kts @@ -1,40 +1,10 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidMultiplatformLibrary) + id("gwenedeg.kmp.library") } kotlin { - iosArm64() - iosSimulatorArm64() - - jvm() - - js { - browser() - } - - @OptIn(ExperimentalWasmDsl::class) - wasmJs { - browser() - } - androidLibrary { namespace = "fr.ajaury.gwenedeg.core.logging" - compileSdk = - libs.versions.androidCompileSdk - .get() - .toInt() - minSdk = - libs.versions.androidMinSdk - .get() - .toInt() - - compilerOptions { - jvmTarget = JvmTarget.JVM_11 - } } sourceSets { @@ -46,8 +16,5 @@ kotlin { implementation(project.dependencies.platform(libs.koin.bom)) implementation(libs.koin.core) } - commonTest.dependencies { - implementation(libs.kotlin.test) - } } } diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts index 5a8f2dc..f248c16 100644 --- a/core/model/build.gradle.kts +++ b/core/model/build.gradle.kts @@ -1,45 +1,9 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidMultiplatformLibrary) + id("gwenedeg.kmp.library") } kotlin { - iosArm64() - iosSimulatorArm64() - - jvm() - - js { - browser() - } - - @OptIn(ExperimentalWasmDsl::class) - wasmJs { - browser() - } - androidLibrary { namespace = "fr.ajaury.gwenedeg.core.model" - compileSdk = - libs.versions.androidCompileSdk - .get() - .toInt() - minSdk = - libs.versions.androidMinSdk - .get() - .toInt() - - compilerOptions { - jvmTarget = JvmTarget.JVM_11 - } - } - - sourceSets { - commonTest.dependencies { - implementation(libs.kotlin.test) - } } } diff --git a/data/records/build.gradle.kts b/data/records/build.gradle.kts index ecbe2f7..1fa8302 100644 --- a/data/records/build.gradle.kts +++ b/data/records/build.gradle.kts @@ -1,40 +1,10 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidMultiplatformLibrary) + id("gwenedeg.kmp.library") } kotlin { - iosArm64() - iosSimulatorArm64() - - jvm() - - js { - browser() - } - - @OptIn(ExperimentalWasmDsl::class) - wasmJs { - browser() - } - androidLibrary { namespace = "fr.ajaury.gwenedeg.records" - compileSdk = - libs.versions.androidCompileSdk - .get() - .toInt() - minSdk = - libs.versions.androidMinSdk - .get() - .toInt() - - compilerOptions { - jvmTarget = JvmTarget.JVM_11 - } } sourceSets { @@ -49,8 +19,5 @@ kotlin { implementation(project.dependencies.platform(libs.koin.bom)) implementation(libs.koin.core) } - commonTest.dependencies { - implementation(libs.kotlin.test) - } } } diff --git a/data/resources/build.gradle.kts b/data/resources/build.gradle.kts index 35a3f54..3166eaf 100644 --- a/data/resources/build.gradle.kts +++ b/data/resources/build.gradle.kts @@ -1,42 +1,11 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidMultiplatformLibrary) - alias(libs.plugins.composeMultiplatform) - alias(libs.plugins.composeCompiler) + id("gwenedeg.kmp.library") + id("gwenedeg.compose") } kotlin { - iosArm64() - iosSimulatorArm64() - - jvm() - - js { - browser() - } - - @OptIn(ExperimentalWasmDsl::class) - wasmJs { - browser() - } - androidLibrary { namespace = "fr.ajaury.gwenedeg.resources" - compileSdk = - libs.versions.androidCompileSdk - .get() - .toInt() - minSdk = - libs.versions.androidMinSdk - .get() - .toInt() - - compilerOptions { - jvmTarget = JvmTarget.JVM_11 - } androidResources { enable = true } diff --git a/data/subtitle/build.gradle.kts b/data/subtitle/build.gradle.kts index f80c1d5..3ae93a6 100644 --- a/data/subtitle/build.gradle.kts +++ b/data/subtitle/build.gradle.kts @@ -1,40 +1,10 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidMultiplatformLibrary) + id("gwenedeg.kmp.library") } kotlin { - iosArm64() - iosSimulatorArm64() - - jvm() - - js { - browser() - } - - @OptIn(ExperimentalWasmDsl::class) - wasmJs { - browser() - } - androidLibrary { namespace = "fr.ajaury.gwenedeg.subtitle" - compileSdk = - libs.versions.androidCompileSdk - .get() - .toInt() - minSdk = - libs.versions.androidMinSdk - .get() - .toInt() - - compilerOptions { - jvmTarget = JvmTarget.JVM_11 - } } sourceSets { @@ -51,8 +21,5 @@ kotlin { implementation(project.dependencies.platform(libs.koin.bom)) implementation(libs.koin.core) } - commonTest.dependencies { - implementation(libs.kotlin.test) - } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 68dc4f0..85b84de 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,6 +21,12 @@ kermit = "2.1.0" vorbisspi = "1.0.3.3" [libraries] +# Gradle plugin artifacts, used by build-logic convention plugins only +android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } +kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +compose-gradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "composeMultiplatform" } +composeCompiler-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" } + androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidxActivity" } compose-components-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "composeMultiplatform" } compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "composeMultiplatform" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 77a6d67..39627e5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,6 +2,7 @@ rootProject.name = "Gwenedeg" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") pluginManagement { + includeBuild("build-logic") repositories { google { mavenContent { diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index f65592e..554fc7b 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,15 +1,12 @@ -import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidMultiplatformLibrary) - alias(libs.plugins.composeMultiplatform) - alias(libs.plugins.composeCompiler) + id("gwenedeg.kmp.library") + id("gwenedeg.compose") alias(libs.plugins.kotlinSerialization) } kotlin { + // Targets are declared by the convention plugin; these calls return the + // existing targets, so this only adds the iOS framework packaging. listOf( iosArm64(), iosSimulatorArm64(), @@ -20,31 +17,8 @@ kotlin { } } - jvm() - - js { - browser() - } - - @OptIn(ExperimentalWasmDsl::class) - wasmJs { - browser() - } - androidLibrary { namespace = "fr.ajaury.gwenedeg.shared" - compileSdk = - libs.versions.androidCompileSdk - .get() - .toInt() - minSdk = - libs.versions.androidMinSdk - .get() - .toInt() - - compilerOptions { - jvmTarget = JvmTarget.JVM_11 - } androidResources { enable = true } @@ -91,9 +65,6 @@ kotlin { implementation(libs.koin.compose) implementation(libs.koin.compose.viewmodel) } - commonTest.dependencies { - implementation(libs.kotlin.test) - } jvmTest.dependencies { // Koin configuration validation implementation(project.dependencies.platform(libs.koin.bom))