Skip to content

Commit 23b8e4a

Browse files
Add convention plugin to share repetitive build configuration code (#12)
1 parent 62440fd commit 23b8e4a

File tree

12 files changed

+175
-179
lines changed

12 files changed

+175
-179
lines changed

convention-plugins/build.gradle.kts

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2+
3+
plugins {
4+
`kotlin-dsl` // Is needed to turn our build logic written in Kotlin into Gradle Plugin
5+
}
6+
7+
dependencies {
8+
compileOnly(libs.kotlin.gradle)
9+
compileOnly(libs.spotless.gradle)
10+
}
11+
12+
gradlePlugin {
13+
plugins {
14+
register("compatibilityConventions") {
15+
id = "conventions.compatibility"
16+
implementationClass = "io.github.podcastindex_sdk.gradle.CompatibilityConventionPlugin"
17+
}
18+
register("spotlessConventions") {
19+
id = "conventions.spotless"
20+
implementationClass = "io.github.podcastindex_sdk.gradle.SpotlessConventionPlugin"
21+
}
22+
}
23+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package io.github.podcastindex_sdk.gradle
2+
3+
import org.gradle.api.Plugin
4+
import org.gradle.api.Project
5+
import org.gradle.api.tasks.compile.JavaCompile
6+
import org.gradle.kotlin.dsl.getByType
7+
import org.gradle.kotlin.dsl.withType
8+
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
9+
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
10+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
11+
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
12+
13+
class CompatibilityConventionPlugin : Plugin<Project> {
14+
15+
override fun apply(target: Project) {
16+
with(target) {
17+
pluginManager.apply("org.jetbrains.kotlin.multiplatform")
18+
pluginManager.apply("dev.drewhamilton.poko")
19+
20+
val kotlinExtension = extensions.getByType<KotlinMultiplatformExtension>()
21+
configureKotlinExtension(kotlinExtension)
22+
}
23+
}
24+
25+
private fun Project.configureKotlinExtension(
26+
kotlinExtension: KotlinMultiplatformExtension
27+
) {
28+
kotlinExtension.apply {
29+
explicitApi()
30+
jvmToolchain(libs.findVersion("jvmToolchain").get().toString().toInt())
31+
32+
jvm()
33+
listOf(
34+
iosX64(),
35+
iosArm64(),
36+
iosSimulatorArm64(),
37+
).forEach {
38+
it.binaries.framework {
39+
baseName = when (this@configureKotlinExtension.name) {
40+
"podcastindex-sdk-base" -> "podcastindex-sdk"
41+
"podcastindex-ktor2" -> "podcastindex-sdk-ktor2"
42+
"podcastindex-ktor3" -> "podcastindex-sdk-ktor3"
43+
else -> error("Unknown project name: ${this@configureKotlinExtension.name}")
44+
}
45+
isStatic = true
46+
}
47+
}
48+
49+
val kotlinTargetVersion = KotlinVersion.fromVersion(libs.findVersion("kotlinTarget").get().toString().toKotlinMinor())
50+
51+
@OptIn(ExperimentalKotlinGradlePluginApi::class)
52+
compilerOptions {
53+
languageVersion.set(kotlinTargetVersion)
54+
apiVersion.set(kotlinTargetVersion)
55+
freeCompilerArgs.add(libs.findVersion("jdkTarget").get().toString().let { "-Xjdk-release=${it.toJdkTarget()}" })
56+
}
57+
coreLibrariesVersion = libs.findVersion("kotlinTarget").get().toString()
58+
}
59+
60+
configureCompilationTasks()
61+
}
62+
63+
private fun Project.configureCompilationTasks() {
64+
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
65+
compilerOptions {
66+
jvmTarget.set(JvmTarget.fromTarget(libs.findVersion("jdkTarget").get().toString().toJdkTarget()))
67+
}
68+
}
69+
70+
tasks.withType<JavaCompile>().configureEach {
71+
sourceCompatibility = libs.findVersion("jdkTarget").get().toString().toJdkTarget()
72+
targetCompatibility = libs.findVersion("jdkTarget").get().toString().toJdkTarget()
73+
}
74+
}
75+
76+
private fun String.toJdkTarget() = if (toInt() <= 8) "1.$this" else this
77+
78+
private fun String.toKotlinMinor() = split(".").take(2).joinToString(".")
79+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.github.podcastindex_sdk.gradle
2+
3+
import org.gradle.api.Project
4+
import org.gradle.api.artifacts.VersionCatalog
5+
import org.gradle.api.artifacts.VersionCatalogsExtension
6+
import org.gradle.kotlin.dsl.getByType
7+
8+
val Project.libs
9+
get(): VersionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.github.podcastindex_sdk.gradle
2+
3+
import com.diffplug.gradle.spotless.SpotlessExtension
4+
import org.gradle.api.Plugin
5+
import org.gradle.api.Project
6+
import org.gradle.kotlin.dsl.getByType
7+
8+
class SpotlessConventionPlugin : Plugin<Project> {
9+
10+
override fun apply(target: Project) {
11+
with(target) {
12+
pluginManager.apply("com.diffplug.spotless")
13+
14+
val spotlessExtension = extensions.getByType<SpotlessExtension>()
15+
configureSpotless(spotlessExtension)
16+
}
17+
}
18+
19+
private fun Project.configureSpotless(
20+
spotlessExtension: SpotlessExtension
21+
) {
22+
spotlessExtension.apply {
23+
kotlin {
24+
target(listOf("*.md", "**/*.kt", ".gitignore", "**/*.gradle.kts"))
25+
ktlint()
26+
trimTrailingWhitespace()
27+
indentWithSpaces(4)
28+
endWithNewline()
29+
}
30+
}
31+
}
32+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@file:Suppress("UnstableApiUsage")
2+
3+
dependencyResolutionManagement {
4+
versionCatalogs {
5+
create("libs") {
6+
from(files("../gradle/libs.versions.toml"))
7+
}
8+
}
9+
10+
repositories {
11+
gradlePluginPortal()
12+
mavenCentral()
13+
}
14+
}
15+
16+
rootProject.name = "convention-plugins"
17+
include(":plugins")

gradle/libs.versions.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ ktor3-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor3"
3030
kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
3131
kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
3232
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
33+
# Convention plugins dependencies
34+
spotless-gradle = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
35+
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
3336

3437
[plugins]
3538

@@ -38,3 +41,5 @@ kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", vers
3841
poko = { id = "dev.drewhamilton.poko", version.ref = "poko" }
3942
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
4043
vanniktech-maven = { id = "com.vanniktech.maven.publish", version.ref = "vanniktech-maven" }
44+
compatibility-conventions = { id = "conventions.compatibility", version = "unspecified" }
45+
spotless-conventions = { id = "conventions.spotless", version = "unspecified" }

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME
Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,13 @@
1-
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
2-
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
3-
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
4-
51
plugins {
6-
alias(libs.plugins.multiplatform)
7-
alias(libs.plugins.spotless)
2+
alias(libs.plugins.compatibility.conventions)
3+
alias(libs.plugins.spotless.conventions)
84
alias(libs.plugins.vanniktech.maven)
95
}
106

117
val GROUP: String by project
128
group = GROUP
139

1410
kotlin {
15-
explicitApi()
16-
jvmToolchain(libs.versions.jvmToolchain.get().toInt())
17-
18-
val kotlinTargetVersion = libs.versions.kotlinTarget.map { KotlinVersion.fromVersion(it.toKotlinMinor()) }
19-
20-
@OptIn(ExperimentalKotlinGradlePluginApi::class)
21-
compilerOptions {
22-
languageVersion = kotlinTargetVersion
23-
apiVersion = kotlinTargetVersion
24-
freeCompilerArgs.add(libs.versions.jdkTarget.map { "-Xjdk-release=${it.toJdkTarget()}" })
25-
}
26-
coreLibrariesVersion = libs.versions.kotlinTarget.get()
27-
28-
jvm()
29-
listOf(
30-
iosX64(),
31-
iosArm64(),
32-
iosSimulatorArm64(),
33-
).forEach {
34-
it.binaries.framework {
35-
baseName = "podcastindex-sdk-ktor2"
36-
isStatic = true
37-
}
38-
}
39-
4011
sourceSets {
4112
commonMain.dependencies {
4213
api(libs.ktor2.core)
@@ -46,7 +17,7 @@ kotlin {
4617
implementation(libs.kermit)
4718
implementation(libs.kotlinx.serialization)
4819
implementation(libs.kotlinx.datetime)
49-
api(project(":podcastindex-sdk-base"))
20+
api(projects.podcastindexSdkBase)
5021
}
5122

5223
jvmMain.dependencies {
@@ -58,28 +29,3 @@ kotlin {
5829
}
5930
}
6031
}
61-
62-
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
63-
compilerOptions {
64-
jvmTarget = libs.versions.jdkTarget.map { JvmTarget.fromTarget(it.toJdkTarget()) }
65-
}
66-
}
67-
68-
tasks.withType<JavaCompile>().configureEach {
69-
sourceCompatibility = libs.versions.jdkTarget.map { it.toJdkTarget() }.get()
70-
targetCompatibility = libs.versions.jdkTarget.map { it.toJdkTarget() }.get()
71-
}
72-
73-
configure<com.diffplug.gradle.spotless.SpotlessExtension> {
74-
kotlin {
75-
target(listOf("*.md", "**/*.kt", ".gitignore", "**/*.gradle.kts"))
76-
ktlint()
77-
trimTrailingWhitespace()
78-
indentWithSpaces(4)
79-
endWithNewline()
80-
}
81-
}
82-
83-
private fun String.toJdkTarget() = if (toInt() <= 8) "1.$this" else this
84-
85-
private fun String.toKotlinMinor() = split(".").take(2).joinToString(".")
Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,13 @@
1-
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
2-
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
3-
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
4-
51
plugins {
6-
alias(libs.plugins.multiplatform)
7-
alias(libs.plugins.spotless)
2+
alias(libs.plugins.compatibility.conventions)
3+
alias(libs.plugins.spotless.conventions)
84
alias(libs.plugins.vanniktech.maven)
95
}
106

117
val GROUP: String by project
128
group = GROUP
139

1410
kotlin {
15-
explicitApi()
16-
jvmToolchain(libs.versions.jvmToolchain.get().toInt())
17-
18-
val kotlinTargetVersion = libs.versions.kotlinTarget.map { KotlinVersion.fromVersion(it.toKotlinMinor()) }
19-
20-
@OptIn(ExperimentalKotlinGradlePluginApi::class)
21-
compilerOptions {
22-
languageVersion = kotlinTargetVersion
23-
apiVersion = kotlinTargetVersion
24-
freeCompilerArgs.add(libs.versions.jdkTarget.map { "-Xjdk-release=${it.toJdkTarget()}" })
25-
}
26-
coreLibrariesVersion = libs.versions.kotlinTarget.get()
27-
28-
jvm()
29-
listOf(
30-
iosX64(),
31-
iosArm64(),
32-
iosSimulatorArm64(),
33-
).forEach {
34-
it.binaries.framework {
35-
baseName = "podcastindex-sdk-ktor3"
36-
isStatic = true
37-
}
38-
}
39-
4011
sourceSets {
4112
commonMain.dependencies {
4213
api(libs.ktor3.core)
@@ -46,7 +17,7 @@ kotlin {
4617
implementation(libs.kermit)
4718
implementation(libs.kotlinx.serialization)
4819
implementation(libs.kotlinx.datetime)
49-
api(project(":podcastindex-sdk-base"))
20+
api(projects.podcastindexSdkBase)
5021
}
5122

5223
jvmMain.dependencies {
@@ -58,28 +29,3 @@ kotlin {
5829
}
5930
}
6031
}
61-
62-
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
63-
compilerOptions {
64-
jvmTarget = libs.versions.jdkTarget.map { JvmTarget.fromTarget(it.toJdkTarget()) }
65-
}
66-
}
67-
68-
tasks.withType<JavaCompile>().configureEach {
69-
sourceCompatibility = libs.versions.jdkTarget.map { it.toJdkTarget() }.get()
70-
targetCompatibility = libs.versions.jdkTarget.map { it.toJdkTarget() }.get()
71-
}
72-
73-
configure<com.diffplug.gradle.spotless.SpotlessExtension> {
74-
kotlin {
75-
target(listOf("*.md", "**/*.kt", ".gitignore", "**/*.gradle.kts"))
76-
ktlint()
77-
trimTrailingWhitespace()
78-
indentWithSpaces(4)
79-
endWithNewline()
80-
}
81-
}
82-
83-
private fun String.toJdkTarget() = if (toInt() <= 8) "1.$this" else this
84-
85-
private fun String.toKotlinMinor() = split(".").take(2).joinToString(".")

0 commit comments

Comments
 (0)