Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fd0cb37
chore(gradle): add build-logic
ArthurKun21 Mar 26, 2026
69875ac
chore: move packages
ArthurKun21 Mar 26, 2026
2c6663f
refactor: rename androidLibrary to android in build logic
ArthurKun21 Mar 26, 2026
fcfa188
chore: add AndroidConfig for SDK version management
ArthurKun21 Mar 27, 2026
bd018f0
refactor: streamline KmpLibraryConventionPlugin configuration
ArthurKun21 Mar 27, 2026
8a59b09
refactor: remove compileSdk and minSdk from build logic
ArthurKun21 Apr 6, 2026
18ec352
refactor: update mavenPublishing coordinates for clarity
ArthurKun21 Apr 6, 2026
e754818
refactor: suppress unstable API usage warnings in build logic
ArthurKun21 Apr 6, 2026
8220b97
refactor: enhance Android configuration setup in build logic
ArthurKun21 Apr 6, 2026
aa65d51
refactor: remove iosX64 configuration from KmpLibraryConventionPlugin
ArthurKun21 Apr 6, 2026
40b9834
refactor: suppress unused warning in MavenPublishConventionPlugin
ArthurKun21 Apr 6, 2026
6470639
refactor: suppress unused warning in SpotlessConventionPlugin
ArthurKun21 Apr 6, 2026
9ecb5a1
refactor: conditionally include sample projects based on JITPACK envi…
ArthurKun21 Apr 6, 2026
a601f43
docs: update iOS target information in Agents.md
ArthurKun21 Apr 6, 2026
5dd2ad6
feat: WIP build-logic
ArthurKun21 Apr 6, 2026
3655cb2
refactor: move files to another package
ArthurKun21 Apr 6, 2026
95d5f73
refactor: simplify Android configuration by extracting setup logic
ArthurKun21 Apr 6, 2026
3706547
refactor: update plugin IDs for consistency and clarity
ArthurKun21 Apr 6, 2026
ff0c603
refactor: streamline Android configuration by applying plugin and set…
ArthurKun21 Apr 6, 2026
2345582
refactor: update plugin IDs for consistency and clarity
ArthurKun21 Apr 6, 2026
a5a79b3
refactor: update spotless plugin ID for consistency across configurat…
ArthurKun21 Apr 6, 2026
e78374e
refactor: change kotlinx.io dependency from api to implementation
ArthurKun21 Apr 6, 2026
e7874dc
refactor: update compose plugin ID for clarity
ArthurKun21 Apr 6, 2026
56546d1
refactor: add KMP library test convention plugin and update build logic
ArthurKun21 Apr 6, 2026
239e730
refactor: update androidDeviceTest dependencies for consistency
ArthurKun21 Apr 6, 2026
23f9f37
refactor: simplify desktop JVM configuration in build logic
ArthurKun21 Apr 6, 2026
3c9188d
refactor: add kotlin-serialization plugin to build logic
ArthurKun21 Apr 6, 2026
2495663
refactor: update build logic for Kotlin serialization plugin
ArthurKun21 Apr 6, 2026
402a7dc
chore(deps): add compose-gradle-plugin 1.10.3
ArthurKun21 Apr 6, 2026
ffffcc9
refactor: update build logic for desktop target and dependencies
ArthurKun21 Apr 6, 2026
125f4f8
docs: update KMP targets in README for iOS architecture
ArthurKun21 Apr 6, 2026
066a370
refactor: streamline KmpLibraryConventionPlugin configuration
ArthurKun21 Apr 6, 2026
566e15e
refactor: simplify configureKmpLibrary function signature
ArthurKun21 Apr 6, 2026
b92e66d
refactor: enhance KmpSampleConventionPlugin with common compile options
ArthurKun21 Apr 6, 2026
9080ac4
refactor: simplify SpotlessConventionPlugin by removing unnecessary code
ArthurKun21 Apr 6, 2026
fcb8c7f
refactor: replace gd.compose plugin with compose.compiler alias
ArthurKun21 Apr 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Both library modules target:

- **Android** (`androidMain`)
- **JVM** (`jvmMain`)
- **iOS** (`iosX64`, `iosArm64`, `iosSimulatorArm64`)
- **iOS** (`iosArm64`, `iosSimulatorArm64`)

## Workflow

Expand Down Expand Up @@ -313,8 +313,8 @@ targets. The compiler reports `Unresolved reference 'SYSTEM'` during iOS publica

**Workaround:** Use the `expect`/`actual` pattern. Declare an `internal expect val` in `commonMain`
and provide `actual` implementations in each platform source set (`androidMain`, `jvmMain`,
`iosMain`) that return `FileSystem.SYSTEM`. The `iosMain` source set covers all three iOS targets
(`iosX64`, `iosArm64`, `iosSimulatorArm64`) via `applyDefaultHierarchyTemplate()`.
`iosMain`) that return `FileSystem.SYSTEM`. The `iosMain` source set covers all two iOS targets
(`iosArm64`, `iosSimulatorArm64`) via `applyDefaultHierarchyTemplate()`.

Files involved:

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ SharedPreferences.

### KMP Targets

Both modules target **Android**, **Desktop (JVM)**, and **iOS** (`iosX64`, `iosArm64`,
Both modules target **Android**, **Desktop (JVM)**, and **iOS** (`iosArm64`,
`iosSimulatorArm64`).

## Installation
Expand Down
44 changes: 44 additions & 0 deletions build-logic/convention/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
plugins {
`kotlin-dsl`
}

dependencies {
compileOnly(libs.android.gradle.plugin)
compileOnly(libs.kotlin.gradle.plugin)
implementation(libs.spotless.gradle.plugin)
compileOnly(libs.compose.gradle.plugin)
compileOnly(libs.vanniktech.maven.publish.plugin)
}

gradlePlugin {
plugins {
register("spotless") {
id = "gd.spotless"
implementationClass = "SpotlessConventionPlugin"
}
register("kmpLibrary") {
id = "gd.kmp.library"
implementationClass = "KmpLibraryConventionPlugin"
}
register("kmpLibraryTest") {
id = "gd.kmp.library.test"
implementationClass = "KmpLibraryTestConventionPlugin"
}
register("mavenPublish") {
id = "gd.maven.publish"
implementationClass = "MavenPublishConventionPlugin"
}
register("compose") {
id = "gd.compose"
implementationClass = "ComposeConventionPlugin"
}
register("kmpSample") {
id = "gd.kmp.sample"
implementationClass = "KmpSampleConventionPlugin"
}
register("androidSampleApp") {
id = "gd.android.sample"
implementationClass = "AndroidSampleAppConventionPlugin"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import com.android.build.api.dsl.ApplicationExtension
import gd.buildlogic.configureAndroid
import gd.buildlogic.configureCommonKotlinCompileOptions
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure

@Suppress("unused")
class AndroidSampleAppConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("com.android.application")
apply("gd.compose")
apply("gd.spotless")
}

extensions.configure<ApplicationExtension> {
configureAndroid(this)

defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildFeatures {
compose = true
}

packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}

configureCommonKotlinCompileOptions()
}
}
}
16 changes: 16 additions & 0 deletions build-logic/convention/src/main/kotlin/ComposeConventionPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import gd.buildlogic.libs
import gd.buildlogic.pluginId
import org.gradle.api.Plugin
import org.gradle.api.Project

@Suppress("unused")
class ComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply(libs.pluginId("compose-compiler"))
apply(libs.pluginId("jetbrains-compose"))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import gd.buildlogic.AndroidConfig
import gd.buildlogic.configureCommonKotlinCompileOptions
import gd.buildlogic.configureKmpLibrary
import gd.buildlogic.libs
import gd.buildlogic.pluginId
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension

@Suppress("unused")
class KmpLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
configureCommonKotlinCompileOptions()

with(pluginManager) {
apply(libs.pluginId("kotlin-multiplatform"))
apply(libs.pluginId("android-library"))
apply("gd.spotless")
}

extensions.configure<KotlinMultiplatformExtension> {
configureKmpLibrary()
explicitApi()

applyDefaultHierarchyTemplate()

targets.withType<KotlinMultiplatformAndroidLibraryTarget>().configureEach {
compileSdk = AndroidConfig.COMPILE_SDK
minSdk = AndroidConfig.MIN_SDK
}

iosArm64()
iosSimulatorArm64()

jvm()

compilerOptions {
freeCompilerArgs.addAll(
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-Xexpect-actual-classes",
)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import gd.buildlogic.library
import gd.buildlogic.libs
import gd.buildlogic.pluginId
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension

class KmpLibraryTestConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply(libs.pluginId("kotlin-multiplatform"))
apply(libs.pluginId("android-library"))
}
extensions.configure<KotlinMultiplatformExtension> {
applyDefaultHierarchyTemplate()

targets.withType<KotlinMultiplatformAndroidLibraryTarget>().configureEach {
withDeviceTestBuilder {
sourceSetTreeName = "test"
}.configure {
instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}

jvm()

sourceSets.apply {
commonTest.dependencies {
implementation(libs.library("kotlin-test"))
implementation(libs.library("coroutines-test"))
}

getByName("androidDeviceTest") {
dependencies {
implementation(libs.library("kotlin-test"))
implementation(libs.library("coroutines-test"))
implementation(libs.library("datastore-preferences"))
implementation(libs.library("junit4"))
implementation(libs.library("androidx-test-junit"))
implementation(libs.library("androidx-test-espresso"))
}
}

jvmTest.dependencies {
implementation(libs.library("junit5"))
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import gd.buildlogic.AndroidConfig
import gd.buildlogic.configureCommonKotlinCompileOptions
import gd.buildlogic.configureKmpLibrary
import gd.buildlogic.library
import gd.buildlogic.libs
import gd.buildlogic.pluginId
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.tasks.testing.Test
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.withType
import org.jetbrains.compose.ComposeExtension
import org.jetbrains.compose.ComposePlugin
import org.jetbrains.compose.desktop.DesktopExtension
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension

@Suppress("unused")
class KmpSampleConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
configureCommonKotlinCompileOptions()

with(pluginManager) {
apply(libs.pluginId("kotlin-multiplatform"))
apply(libs.pluginId("android-library"))
apply(libs.pluginId("kotlin-serialization"))
apply("gd.compose")
apply("gd.spotless")
}

extensions.configure<KotlinMultiplatformExtension> {
configureKmpLibrary()

applyDefaultHierarchyTemplate()

targets.withType<KotlinMultiplatformAndroidLibraryTarget>().configureEach {
compileSdk = AndroidConfig.COMPILE_SDK
minSdk = AndroidConfig.MIN_SDK
}

jvm("desktop")

compilerOptions {
freeCompilerArgs.add("-Xexpect-actual-classes")
}

sourceSets.named("desktopMain") {
dependencies {
implementation(libs.library("coroutines-swing"))
@Suppress("DEPRECATION")
implementation(ComposePlugin.DesktopDependencies.currentOs)
}
}
}

extensions.configure<ComposeExtension> {
extensions.configure<DesktopExtension> {
application {
buildTypes {
release {
proguard {
configurationFiles.from(project.file("proguard-rules.pro"))
}
}
}

nativeDistributions {
modules("jdk.unsupported")
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageVersion = "1.0.0"
}
}
}
}

configureCommonKotlinCompileOptions()

tasks.withType<Test>().configureEach {
useJUnitPlatform()
}

tasks.withType<Jar>().configureEach {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE

exclude("META-INF/AL2.0")
exclude("META-INF/LGPL2.1")
exclude("META-INF/MANIFEST.MF")
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import gd.buildlogic.configureMavenPublish
import org.gradle.api.Plugin
import org.gradle.api.Project

@Suppress("unused")
class MavenPublishConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.vanniktech.maven.publish")

configureMavenPublish()
}
}
}
33 changes: 33 additions & 0 deletions build-logic/convention/src/main/kotlin/SpotlessConventionPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import com.diffplug.gradle.spotless.SpotlessExtension
import gd.buildlogic.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure

@Suppress("unused")
class SpotlessConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply("com.diffplug.spotless")

extensions.configure<SpotlessExtension> {
kotlin {
target("**/*.kt", "**/*.kts")
targetExclude("**/build/**/*.kt")
ktlint(
libs.findLibrary("ktlint-core").get().get().version!!,
).editorConfigOverride(
mapOf("ktlint_standard_annotation" to "disabled"),
)
trimTrailingWhitespace()
endWithNewline()
}
format("xml") {
target("**/*.xml")
trimTrailingWhitespace()
endWithNewline()
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gd.buildlogic

import org.gradle.api.JavaVersion as GradleJavaVersion
import org.jetbrains.kotlin.gradle.dsl.JvmTarget as KotlinJvmTarget

object AndroidConfig {
const val COMPILE_SDK = 36
const val TARGET_SDK = 36
const val MIN_SDK = 24

// https://youtrack.jetbrains.com/issue/KT-66995/JvmTarget-and-JavaVersion-compatibility-for-easier-JVM-version-setup
val JavaVersion = GradleJavaVersion.VERSION_17
val JvmTarget = KotlinJvmTarget.JVM_17
}
Loading
Loading