Extract common build logic to convention plugins

This commit is contained in:
FooIbar committed 2025-08-03 10:39:03 +08:00
1 parent 1a66d84bd0
commit 295770002a
18 files changed
+302 -62

No files matched your search

+3
View File
@@ -42,6 +42,9 @@ jobs:
with:
cache-read-only: true
- name: Check build-logic
run: ./gradlew :build-logic:convention:check
- name: Spotless Check
run: ./gradlew spotlessCheck
+3 -2
View File
@@ -1,8 +1,9 @@
.gradle
/local.properties
.DS_Store
/build
/.kotlin
build
.cxx
.kotlin
*.iml
.idea
.vscode
-2
View File
@@ -1,2 +0,0 @@
/build
/.cxx
+4 -52
View File
@@ -1,20 +1,15 @@
import com.mikepenz.aboutlibraries.plugin.DuplicateMode
import com.mikepenz.aboutlibraries.plugin.DuplicateRule
import java.util.regex.Pattern
import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
val isRelease: Boolean
get() = gradle.startParameter.taskNames.any { it.contains("Release") }
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.ehviewer.android.application)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.ksp)
alias(libs.plugins.spotless)
alias(libs.plugins.aboutlibrariesPlugin)
alias(libs.plugins.composeCompilerReportGenerator)
alias(libs.plugins.baselineprofile)
}
@@ -79,9 +74,10 @@ android {
flavorDimensions += "api"
productFlavors {
create("default")
create("default") {
minSdk = 26
}
create("marshmallow") {
minSdk = 23
applicationIdSuffix = ".m"
versionNameSuffix = "-M"
}
@@ -97,12 +93,6 @@ android {
isCoreLibraryDesugaringEnabled = true
}
lint {
checkReleaseBuilds = false
disable += setOf("MissingTranslation", "MissingQuantity")
error += setOf("InlinedApi")
}
packaging {
dex {
useLegacyPackaging = false
@@ -254,39 +244,14 @@ dependencies {
}
kotlin {
jvmToolchain(21)
// https://kotlinlang.org/docs/gradle-compiler-options.html#all-compiler-options
compilerOptions {
jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
progressiveMode = true
optIn.addAll(
"coil3.annotation.ExperimentalCoilApi",
"androidx.compose.foundation.layout.ExperimentalLayoutApi",
"androidx.compose.material3.ExperimentalMaterial3Api",
"androidx.compose.material3.ExperimentalMaterial3ExpressiveApi",
"androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi",
"androidx.compose.ui.ExperimentalComposeUiApi",
"androidx.compose.foundation.ExperimentalFoundationApi",
"androidx.compose.animation.ExperimentalAnimationApi",
"androidx.compose.animation.ExperimentalSharedTransitionApi",
"androidx.compose.runtime.ExperimentalComposeRuntimeApi",
"androidx.paging.ExperimentalPagingApi",
"kotlin.ExperimentalStdlibApi",
"kotlin.concurrent.atomics.ExperimentalAtomicApi",
"kotlin.contracts.ExperimentalContracts",
"kotlin.time.ExperimentalTime",
"kotlinx.coroutines.ExperimentalCoroutinesApi",
"kotlinx.coroutines.FlowPreview",
"kotlinx.serialization.ExperimentalSerializationApi",
"splitties.experimental.ExperimentalSplittiesApi",
"splitties.preferences.DataStorePreferencesPreview",
)
freeCompilerArgs.addAll(
"-Xcontext-parameters",
"-Xwhen-expressions=indy",
"-Xannotation-default-target=param-property",
)
}
}
@@ -305,16 +270,3 @@ aboutLibraries {
duplicationRule = DuplicateRule.GROUP
}
}
val ktlintVersion = libs.ktlint.get().version
spotless {
kotlin {
// https://github.com/diffplug/spotless/issues/111
target("src/**/*.kt")
ktlint(ktlintVersion)
}
kotlinGradle {
ktlint(ktlintVersion)
}
}
-1
View File
@@ -1 +0,0 @@
/build
+43
View File
@@ -0,0 +1,43 @@
plugins {
`kotlin-dsl`
alias(libs.plugins.spotless)
}
dependencies {
compileOnly(libs.android.gradlePlugin)
compileOnly(libs.kotlin.gradlePlugin)
compileOnly(libs.spotless.gradlePlugin)
}
gradlePlugin {
plugins {
register("androidApplication") {
id = libs.plugins.ehviewer.android.application.get().pluginId
implementationClass = "AndroidApplicationConventionPlugin"
}
register("multiplatformLibrary") {
id = libs.plugins.ehviewer.multiplatform.library.asProvider().get().pluginId
implementationClass = "MultiplatformLibraryConventionPlugin"
}
register("multiplatformLibraryCompose") {
id = libs.plugins.ehviewer.multiplatform.library.compose.get().pluginId
implementationClass = "MultiplatformLibraryComposeConventionPlugin"
}
}
}
kotlin {
jvmToolchain(21)
}
spotless {
val ktlintVersion = libs.ktlint.get().version
kotlin {
// https://github.com/diffplug/spotless/issues/111
target("src/**/*.kt")
ktlint(ktlintVersion)
}
kotlinGradle {
ktlint(ktlintVersion)
}
}
@@ -0,0 +1,37 @@
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.Lint
import com.ehviewer.configureKotlin
import com.ehviewer.configureKotlinCompose
import com.ehviewer.configureLint
import com.ehviewer.configureSpotless
import com.ehviewer.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.assign
import org.gradle.kotlin.dsl.configure
import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidExtension
@Suppress("unused")
class AndroidApplicationConventionPlugin : Plugin<Project> {
override fun apply(target: Project) = with(target) {
apply(plugin = libs.findPlugin("kotlin-android").get().get().pluginId)
apply(plugin = libs.findPlugin("android-application").get().get().pluginId)
apply(plugin = libs.findPlugin("compose-compiler").get().get().pluginId)
apply(plugin = libs.findPlugin("composeCompilerReportGenerator").get().get().pluginId)
configure<KotlinAndroidExtension> {
jvmToolchain(21)
compilerOptions {
configureKotlin()
configureKotlinCompose()
jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
}
}
configure<ApplicationExtension> {
lint(Lint::configureLint)
}
configureSpotless()
}
}
@@ -0,0 +1,23 @@
import com.ehviewer.configureKotlinCompose
import com.ehviewer.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
@Suppress("unused")
class MultiplatformLibraryComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) = with(target) {
apply<MultiplatformLibraryConventionPlugin>()
apply(plugin = libs.findPlugin("compose-compiler").get().get().pluginId)
apply(plugin = libs.findPlugin("compose-multiplatform").get().get().pluginId)
apply(plugin = libs.findPlugin("composeCompilerReportGenerator").get().get().pluginId)
configure<KotlinMultiplatformExtension> {
compilerOptions {
configureKotlinCompose()
}
}
}
}
@@ -0,0 +1,66 @@
import com.android.build.api.dsl.KotlinMultiplatformAndroidLibraryTarget
import com.android.build.api.dsl.Lint
import com.android.build.api.dsl.androidLibrary
import com.ehviewer.configureKotlin
import com.ehviewer.configureLint
import com.ehviewer.configureSpotless
import com.ehviewer.libs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.assign
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
@OptIn(ExperimentalKotlinGradlePluginApi::class)
class MultiplatformLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) = with(target) {
apply(plugin = libs.findPlugin("kotlin-multiplatform").get().get().pluginId)
apply(plugin = libs.findPlugin("android-kotlin-multiplatform-library").get().get().pluginId)
apply(plugin = libs.findPlugin("android-lint").get().get().pluginId)
configure<KotlinMultiplatformExtension> {
jvmToolchain(21)
compilerOptions {
configureKotlin()
}
applyHierarchyTemplate {
common {
group("jvm") {
withCompilations { it.target is KotlinMultiplatformAndroidLibraryTarget }
withJvm()
}
}
}
// jvm("desktop") {
// compilerOptions {
// jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
// }
// }
androidLibrary {
namespace = "com.ehviewer${path.replace(':', '.')}"
withHostTestBuilder {
}
enableCoreLibraryDesugaring = true
compilerOptions {
jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
}
}
}
configure<Lint>(Lint::configureLint)
configureSpotless()
dependencies {
"coreLibraryDesugaring"(libs.findLibrary("desugar").get())
}
}
}
@@ -0,0 +1,36 @@
package com.ehviewer
import org.gradle.kotlin.dsl.assign
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
// https://kotlinlang.org/docs/gradle-compiler-options.html#all-compiler-options
internal fun KotlinCommonCompilerOptions.configureKotlin() {
progressiveMode = true
optIn.addAll(
"kotlin.ExperimentalStdlibApi",
"kotlin.concurrent.atomics.ExperimentalAtomicApi",
"kotlin.contracts.ExperimentalContracts",
"kotlin.time.ExperimentalTime",
"kotlinx.coroutines.ExperimentalCoroutinesApi",
"kotlinx.coroutines.FlowPreview",
)
freeCompilerArgs.addAll(
"-Xcontext-parameters",
"-Xwhen-expressions=indy",
"-Xannotation-default-target=param-property",
)
}
internal fun KotlinCommonCompilerOptions.configureKotlinCompose() {
optIn.addAll(
"androidx.compose.animation.ExperimentalAnimationApi",
"androidx.compose.animation.ExperimentalSharedTransitionApi",
"androidx.compose.foundation.ExperimentalFoundationApi",
"androidx.compose.foundation.layout.ExperimentalLayoutApi",
"androidx.compose.material3.ExperimentalMaterial3Api",
"androidx.compose.material3.ExperimentalMaterial3ExpressiveApi",
"androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi",
"androidx.compose.runtime.ExperimentalComposeRuntimeApi",
"androidx.compose.ui.ExperimentalComposeUiApi",
)
}
@@ -0,0 +1,9 @@
package com.ehviewer
import com.android.build.api.dsl.Lint
internal fun Lint.configureLint() {
checkReleaseBuilds = false
disable += setOf("MissingTranslation", "MissingQuantity")
error += setOf("InlinedApi")
}
@@ -0,0 +1,8 @@
package com.ehviewer
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.getByType
internal val Project.libs
get() = extensions.getByType<VersionCatalogsExtension>().named("libs")
@@ -0,0 +1,22 @@
package com.ehviewer
import com.diffplug.gradle.spotless.SpotlessExtension
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
internal fun Project.configureSpotless() {
apply(plugin = libs.findPlugin("spotless").get().get().pluginId)
configure<SpotlessExtension> {
val ktlintVersion = libs.findLibrary("ktlint").get().get().version
kotlin {
// https://github.com/diffplug/spotless/issues/111
target("src/**/*.kt")
ktlint(ktlintVersion)
}
kotlinGradle {
ktlint(ktlintVersion)
}
}
}
+4
View File
@@ -0,0 +1,4 @@
# Gradle properties are not passed to included builds https://github.com/gradle/gradle/issues/2534
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
+20
View File
@@ -0,0 +1,20 @@
dependencyResolutionManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
rootProject.name = "build-logic"
include(":convention")
+5 -1
View File
@@ -1,7 +1,11 @@
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.kotlin.multiplatform.library) apply false
alias(libs.plugins.android.lint) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.compose.multiplatform) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.spotless) apply false
+16 -2
View File
@@ -16,6 +16,7 @@ androidx-work = "2.10.3"
arrow = "2.1.2"
coil = "3.3.0"
compose-bom = "2025.07.01"
compose-multiplatform = "1.8.2"
compose-destinations = "2.2.0"
compose-preference = "2.1.0"
kotlin = "2.2.20-Beta2"
@@ -27,6 +28,7 @@ ktor = "3.2.3"
okhttp = "5.1.0"
okio = "3.16.0"
splitties = "3.0.0"
spotless = "7.2.1"
telephoto = "0.15.1"
xmlutil = "0.91.2"
junit = "1.3.0"
@@ -121,6 +123,10 @@ androidx-uiautomator = { module = "androidx.test.uiautomator:uiautomator", versi
androidx-benchmark-macro-junit4 = { module = "androidx.benchmark:benchmark-macro-junit4", version.ref = "benchmark" }
androidx-profileinstaller = { module = "androidx.profileinstaller:profileinstaller", version.ref = "profileinstaller" }
android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }
kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
spotless-gradlePlugin = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
[bundles]
arrow = ["arrow-fx-coroutines", "arrow-functions", "arrow-resilience"]
coil = ["coil-compose", "coil-gif", "coil-network"]
@@ -131,11 +137,19 @@ splitties = ["splitties-appctx", "splitties-arch-room", "splitties-preferences",
[plugins]
aboutlibrariesPlugin = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutlibraries" }
android-application = { id = "com.android.application", version.ref = "agp" }
android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
android-lint = { id = "com.android.lint", version.ref = "agp" }
composeCompilerReportGenerator = { id = "dev.shreyaspatil.compose-compiler-report-generator", version = "1.4.2" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
spotless = { id = "com.diffplug.spotless", version = "7.2.1" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
android-test = { id = "com.android.test", version.ref = "agp" }
baselineprofile = { id = "androidx.baselineprofile", version.ref = "benchmark" }
ehviewer-android-application = { id = "ehviewer.android.application" }
ehviewer-multiplatform-library = { id = "ehviewer.multiplatform.library" }
ehviewer-multiplatform-library-compose = { id = "ehviewer.multiplatform.library.compose" }
+3 -2
View File
@@ -1,6 +1,6 @@
pluginManagement {
includeBuild("build-logic")
repositories {
gradlePluginPortal()
google {
content {
includeGroupByRegex("com\\.android.*")
@@ -9,6 +9,7 @@ pluginManagement {
}
}
mavenCentral()
gradlePluginPortal()
}
}
@@ -32,7 +33,7 @@ plugins {
android {
compileSdk = 36
minSdk = 26
minSdk = 23
targetSdk = 36
ndkVersion = "28.2.13676358"
buildToolsVersion = "36.0.0"