From 4fb4be1fc57b4e6565d9da20f64d7102eebc096c Mon Sep 17 00:00:00 2001 From: Chris Keenan <10093880+chRyNaN@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:06:41 -0400 Subject: [PATCH] Added build-logic module --- build-logic/build.gradle.kts | 17 +++ build-logic/settings.gradle.kts | 28 +++++ .../src/main/kotlin/BuildVariablesPlugin.kt | 48 +++++++ .../src/main/kotlin/LibraryConstants.kt | 11 ++ .../parcelable.multiplatform.gradle.kts | 109 ++++++++++++++++ .../main/kotlin/parcelable.publish.gradle.kts | 118 ++++++++++++++++++ build-logic/versions.properties | 12 ++ build.gradle.kts | 29 +---- .../LibraryConstants.kt | 20 --- .../OsUtils.kt | 30 ----- gradle.properties | 22 +++- library.properties | 2 + parcelable-compose/build.gradle.kts | 43 ++----- parcelable-core/Module.md | 3 - parcelable-core/build.gradle.kts | 85 +------------ sample-compose/build.gradle.kts | 1 - sample-core/build.gradle.kts | 1 - settings.gradle.kts | 11 +- versions.properties | 2 +- 19 files changed, 391 insertions(+), 201 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/BuildVariablesPlugin.kt create mode 100644 build-logic/src/main/kotlin/LibraryConstants.kt create mode 100644 build-logic/src/main/kotlin/parcelable.multiplatform.gradle.kts create mode 100644 build-logic/src/main/kotlin/parcelable.publish.gradle.kts create mode 100644 build-logic/versions.properties delete mode 100644 buildSrc/src/main/java/com.chrynan.parcelable.buildSrc/LibraryConstants.kt delete mode 100644 buildSrc/src/main/java/com.chrynan.parcelable.buildSrc/OsUtils.kt create mode 100644 library.properties delete mode 100644 parcelable-core/Module.md diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts new file mode 100644 index 0000000..4c7c795 --- /dev/null +++ b/build-logic/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + `kotlin-dsl` +} + +dependencies { + implementation(Kotlin.stdlib) + implementation(Kotlin.gradlePlugin) + + implementation("com.mooncloak.kodetools.kenv:kenv-core:_") +} + +gradlePlugin { + plugins.register("parcelable.variables") { + id = "parcelable.variables" + implementationClass = "BuildVariablesPlugin" + } +} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 0000000..c3a8382 --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,28 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven("https://plugins.gradle.org/m2/") + mavenCentral() + google() + } +} + +dependencyResolutionManagement { + @Suppress("UnstableApiUsage") + repositories { + mavenCentral() + google() + gradlePluginPortal() + maven("https://repo.repsy.io/mvn/mooncloak/public") + } +} + +plugins { + // This is the plugin we use to handle our dependency versions. See the versions.properties file for the latest versions. + // See https://jmfayard.github.io/refreshVersions + id("de.fayard.refreshVersions") version "0.60.5" + + // See root build.gradle.kts file for the rest of the plugins applied. +} + +rootProject.name = "build-logic" diff --git a/build-logic/src/main/kotlin/BuildVariablesPlugin.kt b/build-logic/src/main/kotlin/BuildVariablesPlugin.kt new file mode 100644 index 0000000..4bb9dfb --- /dev/null +++ b/build-logic/src/main/kotlin/BuildVariablesPlugin.kt @@ -0,0 +1,48 @@ +import com.mooncloak.kodetools.kenv.Kenv +import com.mooncloak.kodetools.kenv.properties +import org.gradle.api.Plugin +import org.gradle.api.Project + +abstract class BuildVariablesPlugin : Plugin { + + override fun apply(target: Project) { + projectBuildVariables[target.name] = BuildVariables( + kenv = Kenv { + system() + properties(file = target.rootProject.layout.projectDirectory.file("library.properties").asFile) + } + ) + } +} + +class BuildVariables internal constructor( + private val kenv: Kenv +) { + + val group: String + get() = kenv["group"].value + + val version: String + get() = kenv["version"].value + + val versionCode: Int + get() = TODO("Use git commit count.") +} + +val Project.buildVariables: BuildVariables + get() { + var variables = projectBuildVariables[this.name] + + if (variables == null) { + this.logger.warn("The '${BuildVariablesPlugin::class.simpleName}' was not applied to project with name '${this.name}'. Attempting to load root project build variables.") + } + + if (this != this.rootProject) { + variables = projectBuildVariables[this.rootProject.name] + } + + return variables + ?: error("Failed to load required build variables. Make sure the '${BuildVariablesPlugin::class.simpleName}' is applied to the project.") + } + +private val projectBuildVariables = mutableMapOf() diff --git a/build-logic/src/main/kotlin/LibraryConstants.kt b/build-logic/src/main/kotlin/LibraryConstants.kt new file mode 100644 index 0000000..72420c2 --- /dev/null +++ b/build-logic/src/main/kotlin/LibraryConstants.kt @@ -0,0 +1,11 @@ +@file:Suppress("MemberVisibilityCanBePrivate") + +object LibraryConstants { + + object Android { + + const val compileSdkVersion = 34 + const val minSdkVersion = 21 + const val targetSdkVersion = 34 + } +} diff --git a/build-logic/src/main/kotlin/parcelable.multiplatform.gradle.kts b/build-logic/src/main/kotlin/parcelable.multiplatform.gradle.kts new file mode 100644 index 0000000..3b67d8f --- /dev/null +++ b/build-logic/src/main/kotlin/parcelable.multiplatform.gradle.kts @@ -0,0 +1,109 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask +import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.tasks.KotlinTest + +plugins { + kotlin("multiplatform") +} + +kotlin { + applyDefaultHierarchyTemplate() + + js { + browser { + testTask { + enabled = false + } + } + nodejs { + testTask { + enabled = false + } + } + + binaries.executable() + } + + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + browser { + testTask { + enabled = false + } + } + nodejs { + testTask { + enabled = false + } + } + + binaries.executable() + } + + //@OptIn(ExperimentalWasmDsl::class) + // TODO: Re-enable when library supports WASI: wasmWasi() + + linuxArm64() + linuxX64() + + mingwX64() + + macosX64() + macosArm64() + + iosArm64() + iosX64() + iosSimulatorArm64() + + tvosArm64() + tvosX64() + tvosSimulatorArm64() + + watchosArm32() + watchosArm64() + watchosX64() + watchosSimulatorArm64() + + androidTarget { + publishAllLibraryVariants() + } + + jvm() + + explicitApi() + + // Ensure xml test reports are generated + tasks.named("jvmTest", Test::class).configure { + reports.junitXml.required.set(true) + } +} + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +tasks.withType().configureEach { + compilerOptions.jvmTarget = JvmTarget.JVM_11 +} + +tasks.withType { + if (targetName == "tvosSimulatorArm64" || targetName == "watchosSimulatorArm64") { + enabled = false + } +} + +// Don't run npm install scripts, protects against +// https://blog.jetbrains.com/kotlin/2021/10/important-ua-parser-js-exploit-and-kotlin-js/ etc. +tasks.withType { + args += "--ignore-scripts" +} + +tasks.withType>().configureEach { + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } +} diff --git a/build-logic/src/main/kotlin/parcelable.publish.gradle.kts b/build-logic/src/main/kotlin/parcelable.publish.gradle.kts new file mode 100644 index 0000000..f43bd88 --- /dev/null +++ b/build-logic/src/main/kotlin/parcelable.publish.gradle.kts @@ -0,0 +1,118 @@ +plugins { + `maven-publish` + signing +} + +version = rootProject.version +group = rootProject.group + +afterEvaluate { + publishing { + repositories { + maven { // TODO: Update to use mavenCentral + url = uri("https://repo.repsy.io/mvn/chrynan/public") + + credentials { + username = (project.findProperty("repsyUsername") + ?: System.getenv("repsyUsername")) as? String + + password = (project.findProperty("repsyPassword") + ?: System.getenv("repsyPassword")) as? String + } + } + } + + if (plugins.hasPlugin("org.jetbrains.kotlin.multiplatform")) { + // already has publications, just need to add javadoc task + val javadocJar by tasks.creating(Jar::class) { + from("javadoc") + archiveClassifier.set("javadoc") + } + + publications.all { + if (this is MavenPublication) { + artifact(javadocJar) + mavenCentralPom() + } + } + + // create task to publish all apple (macos, ios, tvos, watchos) artifacts + val publishApple by tasks.registering { + publications.all { + if (name.contains(Regex("macos|ios|tvos|watchos"))) { + val publicationNameForTask = name.replaceFirstChar(Char::uppercase) + dependsOn("publish${publicationNameForTask}PublicationToSonatypeRepository") + } + } + } + } else { + // Need to create source, javadoc & publication + val java = extensions.getByType() + + java.withSourcesJar() + java.withJavadocJar() + + publications { + create("lib") { + from(components["java"]) + mavenCentralPom() + } + } + } + } +} + +fun MavenPublication.mavenCentralPom() { + pom { + name.set("serialization-parcelable") + description.set("Android Parcelable support for the Kotlinx Serialization library.") + url.set("https://github.com/chRyNaN/serialization-parcelable") + + organization { + url.set("https://chrynan.codes") + name.set("chRyNaN") + } + + issueManagement { + url.set("https://github.com/chRyNaN/serialization-parcelable/issues") + system.set("Github Issues") + } + + licenses { + license { + name.set("The Apache License, Version 2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") + } + } + + developers { + developer { + id.set("ckeenan") + name.set("Chris Keenan") + url.set("https://github.com/chRyNaN") + roles.set(setOf("Primary serialization-parcelable developer. 💪")) + } + } + + scm { + connection.set("https://github.com/chRyNaN/serialization-parcelable.git") + developerConnection.set("https://github.com/chRyNaN/serialization-parcelable.git") + url.set("https://github.com/chRyNaN/serialization-parcelable") + } + } +} + +signing { + setRequired { + findProperty("signing.keyId") != null + } + + publishing.publications.all { + sign(this) + } +} + +// TODO: remove after https://youtrack.jetbrains.com/issue/KT-46466 is fixed +project.tasks.withType(AbstractPublishToMaven::class.java).configureEach { + dependsOn(project.tasks.withType(Sign::class.java)) +} diff --git a/build-logic/versions.properties b/build-logic/versions.properties new file mode 100644 index 0000000..813af4e --- /dev/null +++ b/build-logic/versions.properties @@ -0,0 +1,12 @@ +#### Dependencies and Plugin versions with their available updates. +#### Generated by `./gradlew refreshVersions` version 0.60.5 +#### +#### Don't manually edit or split the comments that start with four hashtags (####), +#### they will be overwritten by refreshVersions. +#### +#### suppress inspection "SpellCheckingInspection" for whole file +#### suppress inspection "UnusedProperty" for whole file + +version.com.mooncloak.kodetools.kenv..kenv-core=1.2.0 + +version.kotlin=2.0.20 diff --git a/build.gradle.kts b/build.gradle.kts index dd2ae33..0c7ca9b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,3 @@ -import com.chrynan.parcelable.buildSrc.LibraryConstants - -group = LibraryConstants.group -version = LibraryConstants.versionName - plugins { kotlin("jvm") version "2.0.20" apply false kotlin("multiplatform") version "2.0.20" apply false @@ -15,29 +10,13 @@ plugins { id("org.jetbrains.kotlin.plugin.compose") version "2.0.0" apply false id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.13.2" id("com.vanniktech.dependency.graph.generator") version "0.7.0" -} - -allprojects { - repositories { - google() - mavenCentral() - maven { url = uri("https://repo.repsy.io/mvn/chrynan/public") } - maven { url = uri("https://maven.pkg.jetbrains.space/public/p/compose/dev") } - } -} - -rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin::class.java) { - rootProject.the().yarnLockMismatchReport = - org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockMismatchReport.WARNING // NONE | FAIL - rootProject.the().reportNewYarnLock = false // true - rootProject.the().yarnLockAutoReplace = false // true -} - -rootProject.plugins.withType { - rootProject.the().nodeVersion = "16.0.0" + id("parcelable.variables") } // Documentation tasks.named("dokkaGfmMultiModule").configure { outputDirectory.set(file("${projectDir.path}/docs")) } + +group = buildVariables.group +version = buildVariables.version diff --git a/buildSrc/src/main/java/com.chrynan.parcelable.buildSrc/LibraryConstants.kt b/buildSrc/src/main/java/com.chrynan.parcelable.buildSrc/LibraryConstants.kt deleted file mode 100644 index 3696f69..0000000 --- a/buildSrc/src/main/java/com.chrynan.parcelable.buildSrc/LibraryConstants.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.chrynan.parcelable.buildSrc - -object LibraryConstants { - - const val group = "com.chrynan.parcelable" - const val owner = "chrynan" - const val repoName = "parcelable" - const val versionName = "0.8.0" - const val versionCode = 13 - const val versionDescription = "Release $versionName ($versionCode)" - const val license = "Apache-2.0" - const val vcsUrl = "https://github.com/chRyNaN/pacelable.git" - - object Android { - - const val compileSdkVersion = 34 - const val minSdkVersion = 21 - const val targetSdkVersion = 34 - } -} diff --git a/buildSrc/src/main/java/com.chrynan.parcelable.buildSrc/OsUtils.kt b/buildSrc/src/main/java/com.chrynan.parcelable.buildSrc/OsUtils.kt deleted file mode 100644 index 385297c..0000000 --- a/buildSrc/src/main/java/com.chrynan.parcelable.buildSrc/OsUtils.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.chrynan.parcelable.buildSrc - -import java.lang.System - -/** - * Determines if this Gradle build is running on a Mac OSX Operating System. - */ -fun isBuildingOnOSX(): Boolean { - val osName = System.getProperty("os.name").toLowerCase() - - return osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx") -} - -/** - * Determines if this Gradle build is running on a Linux Operating System. - */ -fun isBuildingOnLinux(): Boolean { - val osName = System.getProperty("os.name").toLowerCase() - - return osName.contains("linux") -} - -/** - * Determines if this Gradle build is running on a Windows Operating System. - */ -fun isBuildingOnWindows(): Boolean { - val osName = System.getProperty("os.name").toLowerCase() - - return osName.contains("windows") || osName.contains("mingw") -} diff --git a/gradle.properties b/gradle.properties index c287b51..e1e8886 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,21 @@ -kotlin.code.style=official -kotlin.native.distribution.type=prebuilt +# Android android.useAndroidX=true + +# Kotlin +kotlin.code.style=official +kotlin.mpp.stability.nowarn=true +kotlin.mpp.enableCInteropCommonization=true +kotlin.mpp.androidSourceSetLayoutVersion=2 +# Experimental: Faster Builds + Possible Build Issues +kotlin.incremental.native=true + +# Compose +org.jetbrains.compose.experimental.uikit.enabled=true +org.jetbrains.compose.experimental.macos.enabled=true +org.jetbrains.compose.experimental.jscanvas.enabled=true +org.jetbrains.compose.experimental.wasm.enabled=true + +# Gradle +org.gradle.console=rich +org.gradle.jvmargs=-Xmx8g +kotlin.daemon.jvmargs=-Xmx8g \ No newline at end of file diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..41ce51b --- /dev/null +++ b/library.properties @@ -0,0 +1,2 @@ +group=com.chrynan.parcelable +version=0.8.0 diff --git a/parcelable-compose/build.gradle.kts b/parcelable-compose/build.gradle.kts index 75a9edf..7919100 100644 --- a/parcelable-compose/build.gradle.kts +++ b/parcelable-compose/build.gradle.kts @@ -1,5 +1,3 @@ -import com.chrynan.parcelable.buildSrc.LibraryConstants -import com.chrynan.parcelable.buildSrc.isBuildingOnOSX import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -9,11 +7,9 @@ plugins { id("org.jetbrains.dokka") id("org.jetbrains.compose") id("org.jetbrains.kotlin.plugin.compose") + id("parcelable.publish") } -group = LibraryConstants.group -version = LibraryConstants.versionName - kotlin { applyDefaultHierarchyTemplate() @@ -30,13 +26,11 @@ kotlin { browser() } - if (isBuildingOnOSX()) { - iosX64() - iosArm64() - iosSimulatorArm64() - macosX64() - macosArm64() - } + iosX64() + iosArm64() + iosSimulatorArm64() + macosX64() + macosArm64() sourceSets { all { @@ -65,11 +59,9 @@ kotlin { } } - if (isBuildingOnOSX()) { - val iosMain by sourceSets.getting - val iosSimulatorArm64Main by sourceSets.getting - iosSimulatorArm64Main.dependsOn(iosMain) - } + val iosMain by sourceSets.getting + val iosSimulatorArm64Main by sourceSets.getting + iosSimulatorArm64Main.dependsOn(iosMain) } } @@ -113,20 +105,3 @@ android { } tasks.withType { duplicatesStrategy = DuplicatesStrategy.INHERIT } - -afterEvaluate { - publishing { - repositories { - maven { - url = uri("https://repo.repsy.io/mvn/chrynan/public") - - credentials { - username = (project.findProperty("repsyUsername") - ?: System.getenv("repsyUsername")) as? String - password = (project.findProperty("repsyToken") - ?: System.getenv("repsyToken")) as? String - } - } - } - } -} diff --git a/parcelable-core/Module.md b/parcelable-core/Module.md deleted file mode 100644 index 7e074c4..0000000 --- a/parcelable-core/Module.md +++ /dev/null @@ -1,3 +0,0 @@ -# Module parcelable-core - -Contains the core components for connecting Parcelable with kotlinx.serialization. diff --git a/parcelable-core/build.gradle.kts b/parcelable-core/build.gradle.kts index 5f6c176..2b57866 100644 --- a/parcelable-core/build.gradle.kts +++ b/parcelable-core/build.gradle.kts @@ -1,81 +1,21 @@ -import com.chrynan.parcelable.buildSrc.LibraryConstants -import com.chrynan.parcelable.buildSrc.isBuildingOnLinux -import com.chrynan.parcelable.buildSrc.isBuildingOnOSX -import com.chrynan.parcelable.buildSrc.isBuildingOnWindows import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { kotlin("multiplatform") id("com.android.library") - id("maven-publish") id("org.jetbrains.dokka") + id("parcelable.multiplatform") + id("parcelable.publish") } -group = LibraryConstants.group -version = LibraryConstants.versionName - kotlin { - applyDefaultHierarchyTemplate() - - androidTarget { - publishAllLibraryVariants() - } - - jvm() - - js(IR) { - browser { - testTask { - enabled = false - } - } - nodejs { - testTask { - enabled = false - } - } - } - - @Suppress("OPT_IN_USAGE") - wasmJs { - browser { - testTask { - enabled = false - } - } - nodejs { - testTask { - enabled = false - } - } - } - - if (isBuildingOnOSX()) { - iosX64() - iosArm64() - iosSimulatorArm64() - tvosX64() - tvosArm64() - watchosX64() - watchosArm64() - macosX64() - macosArm64() - } - - if (isBuildingOnLinux()) { - linuxX64() - } - - if (isBuildingOnWindows()) { - mingwX64() - } - sourceSets { val commonMain by getting { dependencies { // kotlinx.serialization - api("org.jetbrains.kotlinx:kotlinx-serialization-core:_") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:_") + // https://github.com/Kotlin/kotlinx.serialization + api(KotlinX.serialization.core) + implementation(KotlinX.serialization.json) } } @@ -138,18 +78,3 @@ android { } tasks.withType { duplicatesStrategy = DuplicatesStrategy.INHERIT } - -afterEvaluate { - publishing { - repositories { - maven { - url = uri("https://repo.repsy.io/mvn/chrynan/public") - - credentials { - username = (project.findProperty("repsyUsername") ?: System.getenv("repsyUsername")) as? String - password = (project.findProperty("repsyToken") ?: System.getenv("repsyToken")) as? String - } - } - } - } -} diff --git a/sample-compose/build.gradle.kts b/sample-compose/build.gradle.kts index 931f2cd..9feb624 100644 --- a/sample-compose/build.gradle.kts +++ b/sample-compose/build.gradle.kts @@ -1,4 +1,3 @@ -import com.chrynan.parcelable.buildSrc.LibraryConstants import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.compose.compose diff --git a/sample-core/build.gradle.kts b/sample-core/build.gradle.kts index 06430ec..7c13f31 100644 --- a/sample-core/build.gradle.kts +++ b/sample-core/build.gradle.kts @@ -1,4 +1,3 @@ -import com.chrynan.parcelable.buildSrc.LibraryConstants import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/settings.gradle.kts b/settings.gradle.kts index 069499b..0fa525d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,17 +5,22 @@ pluginManagement { mavenCentral() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental") - maven { url = uri("https://repo.repsy.io/mvn/chrynan/public") } + maven("https://repo.repsy.io/mvn/chrynan/public") + maven("https://repo.repsy.io/mvn/mooncloak/public") } + + includeBuild("build-logic") } dependencyResolutionManagement { + @Suppress("UnstableApiUsage") repositories { mavenCentral() google() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental") maven("https://repo.repsy.io/mvn/chrynan/public") + maven("https://repo.repsy.io/mvn/mooncloak/public") } } @@ -24,9 +29,7 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" // See https://jmfayard.github.io/refreshVersions - id("de.fayard.refreshVersions") version "0.60.3" -//// # available:"0.60.4" -//// # available:"0.60.5" + id("de.fayard.refreshVersions") version "0.60.5" } rootProject.name = "parcelable" diff --git a/versions.properties b/versions.properties index e777581..73052a1 100644 --- a/versions.properties +++ b/versions.properties @@ -1,5 +1,5 @@ #### Dependencies and Plugin versions with their available updates. -#### Generated by `./gradlew refreshVersions` version 0.60.3 +#### Generated by `./gradlew refreshVersions` version 0.60.5 #### #### Don't manually edit or split the comments that start with four hashtags (####), #### they will be overwritten by refreshVersions.