diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 00ba2c765b..a0f66ecfda 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -7,9 +7,8 @@ import java.time.format.DateTimeFormatter import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - alias(androidx.plugins.application) - alias(kotlinx.plugins.android) - alias(kotlinx.plugins.compose.compiler) + id("yokai.android.application") + id("yokai.android.application.compose") alias(kotlinx.plugins.serialization) alias(kotlinx.plugins.parcelize) alias(libs.plugins.aboutlibraries) @@ -122,7 +121,6 @@ android { buildFeatures { viewBinding = true - compose = true // If you're here because there's not BuildConfig, build the app first, it'll generate it for you buildConfig = true @@ -284,13 +282,12 @@ tasks { // "-opt-in=kotlin.Experimental", "-opt-in=kotlin.RequiresOptIn", "-opt-in=kotlin.ExperimentalStdlibApi", + "-opt-in=coil3.annotation.ExperimentalCoilApi", "-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi", "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api", "-opt-in=androidx.compose.ui.ExperimentalComposeUiApi", "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", "-opt-in=androidx.compose.animation.ExperimentalAnimationApi", - // "-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi", - "-opt-in=coil3.annotation.ExperimentalCoilApi", // "-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi", "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", "-opt-in=kotlinx.coroutines.FlowPreview", @@ -298,19 +295,6 @@ tasks { "-opt-in=kotlinx.coroutines.InternalCoroutinesApi", "-opt-in=kotlinx.serialization.ExperimentalSerializationApi", ) - - if (project.findProperty("tachiyomi.enableComposeCompilerMetrics") == "true") { - compilerOptions.freeCompilerArgs.addAll( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + - (project.layout.buildDirectory.asFile.orNull?.absolutePath ?: "/tmp/yokai") + "/compose_metrics", - ) - compilerOptions.freeCompilerArgs.addAll( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + - (project.layout.buildDirectory.asFile.orNull?.absolutePath ?: "/tmp/yokai") + "/compose_metrics", - ) - } } // Duplicating Hebrew string assets due to some locale code issues on different devices diff --git a/build.gradle.kts b/build.gradle.kts index b85331dcda..d5c90cc3b8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,12 +8,6 @@ import java.util.* plugins { alias(libs.plugins.kotlinter) alias(libs.plugins.gradle.versions) - alias(androidx.plugins.application) apply false - alias(androidx.plugins.library) apply false - alias(kotlinx.plugins.android) apply false - alias(kotlinx.plugins.compose.compiler) apply false - alias(kotlinx.plugins.multiplatform) apply false - alias(kotlinx.plugins.parcelize) apply false alias(kotlinx.plugins.serialization) apply false alias(libs.plugins.aboutlibraries) apply false alias(libs.plugins.firebase.crashlytics) apply false @@ -22,46 +16,6 @@ plugins { alias(libs.plugins.sqldelight) apply false } -subprojects { - tasks.withType { - compilerOptions { - jvmTarget = JvmTarget.JVM_17 - } - } - - tasks.withType { - useJUnitPlatform() - testLogging { - events(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED) - } - } - - plugins.withType { - configure { - compileSdkVersion(AndroidConfig.compileSdk) - ndkVersion = AndroidConfig.ndk - - defaultConfig { - minSdk = AndroidConfig.minSdk - targetSdk = AndroidConfig.targetSdk - ndk { - version = AndroidConfig.ndk - } - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - isCoreLibraryDesugaringEnabled = true - } - - dependencies { - add("coreLibraryDesugaring", libs.desugar) - } - } - } -} - tasks.named("dependencyUpdates", com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask::class.java).configure { rejectVersionIf { val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { candidate.version.uppercase(Locale.ROOT).contains(it) } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 88cd14f786..b825b41720 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,6 +1,21 @@ plugins { `kotlin-dsl` } + +dependencies { + implementation(androidx.gradle) + implementation(kotlinx.gradle) + implementation(kotlinx.compose.compiler.gradle) + implementation(gradleApi()) + + implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) + implementation(files(androidx.javaClass.superclass.protectionDomain.codeSource.location)) + implementation(files(compose.javaClass.superclass.protectionDomain.codeSource.location)) + implementation(files(kotlinx.javaClass.superclass.protectionDomain.codeSource.location)) +} + repositories { + gradlePluginPortal() mavenCentral() -} \ No newline at end of file + google() +} diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 5b387ffc76..df8c5a31ee 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -1 +1,18 @@ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + create("androidx") { + from(files("../gradle/androidx.versions.toml")) + } + create("compose") { + from(files("../gradle/compose.versions.toml")) + } + create("kotlinx") { + from(files("../gradle/kotlinx.versions.toml")) + } + } +} + rootProject.name = "yokai-buildSrc" diff --git a/buildSrc/src/main/kotlin/AndroidConfig.kt b/buildSrc/src/main/kotlin/AndroidConfig.kt index 742ae66247..025e0fd522 100644 --- a/buildSrc/src/main/kotlin/AndroidConfig.kt +++ b/buildSrc/src/main/kotlin/AndroidConfig.kt @@ -1,6 +1,9 @@ +import org.gradle.api.JavaVersion as GradleJavaVersion + object AndroidConfig { - const val compileSdk = 35 - const val minSdk = 23 - const val targetSdk = 35 - const val ndk = "27.2.12479018" + const val COMPILE_SDK = 35 + const val MIN_SDK = 23 + const val TARGET_SDK = 35 + const val NDK = "27.2.12479018" + val JavaVersion = GradleJavaVersion.VERSION_17 } diff --git a/buildSrc/src/main/kotlin/yokai.android.application.compose.gradle.kts b/buildSrc/src/main/kotlin/yokai.android.application.compose.gradle.kts new file mode 100644 index 0000000000..3bb076cfe8 --- /dev/null +++ b/buildSrc/src/main/kotlin/yokai.android.application.compose.gradle.kts @@ -0,0 +1,10 @@ +import yokai.build.configureCompose + +plugins { + id("com.android.application") + kotlin("android") +} + +android { + configureCompose(this) +} diff --git a/buildSrc/src/main/kotlin/yokai.android.application.gradle.kts b/buildSrc/src/main/kotlin/yokai.android.application.gradle.kts new file mode 100644 index 0000000000..70f34fcad5 --- /dev/null +++ b/buildSrc/src/main/kotlin/yokai.android.application.gradle.kts @@ -0,0 +1,15 @@ +import yokai.build.configureAndroid +import yokai.build.configureTest + +plugins { + id("com.android.application") + kotlin("android") +} + +android { + defaultConfig { + targetSdk = AndroidConfig.TARGET_SDK + } + configureAndroid(this) + configureTest() +} diff --git a/buildSrc/src/main/kotlin/yokai.android.library.compose.gradle.kts b/buildSrc/src/main/kotlin/yokai.android.library.compose.gradle.kts new file mode 100644 index 0000000000..fed5d565de --- /dev/null +++ b/buildSrc/src/main/kotlin/yokai.android.library.compose.gradle.kts @@ -0,0 +1,9 @@ +import yokai.build.configureCompose + +plugins { + id("com.android.library") +} + +android { + configureCompose(this) +} diff --git a/buildSrc/src/main/kotlin/yokai.android.library.gradle.kts b/buildSrc/src/main/kotlin/yokai.android.library.gradle.kts new file mode 100644 index 0000000000..7dd7d66697 --- /dev/null +++ b/buildSrc/src/main/kotlin/yokai.android.library.gradle.kts @@ -0,0 +1,11 @@ +import yokai.build.configureAndroid +import yokai.build.configureTest + +plugins { + id("com.android.library") +} + +android { + configureAndroid(this) + configureTest() +} diff --git a/buildSrc/src/main/kotlin/yokai/build/ProjectExtensions.kt b/buildSrc/src/main/kotlin/yokai/build/ProjectExtensions.kt index df362eaefc..cee0c412ac 100644 --- a/buildSrc/src/main/kotlin/yokai/build/ProjectExtensions.kt +++ b/buildSrc/src/main/kotlin/yokai/build/ProjectExtensions.kt @@ -1,6 +1,98 @@ package yokai.build +import com.android.build.api.dsl.CommonExtension +import org.gradle.accessors.dm.LibrariesForAndroidx +import org.gradle.accessors.dm.LibrariesForCompose +import org.gradle.accessors.dm.LibrariesForKotlinx +import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.api.Project +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.provideDelegate +import org.gradle.kotlin.dsl.the +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension +import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.io.File +val Project.androidx get() = the() +val Project.compose get() = the() +val Project.kotlinx get() = the() +val Project.libs get() = the() + val Project.generatedBuildDir: File get() = project.layout.buildDirectory.asFile.get().resolve("generated/yokai") + +internal fun Project.configureAndroid(commonExtension: CommonExtension<*, *, *, *, *, *>) { + commonExtension.apply { + compileSdk = AndroidConfig.COMPILE_SDK + defaultConfig { + minSdk = AndroidConfig.MIN_SDK + ndk { + version = AndroidConfig.NDK + } + } + compileOptions { + sourceCompatibility = AndroidConfig.JavaVersion + targetCompatibility = AndroidConfig.JavaVersion + isCoreLibraryDesugaringEnabled = true + } + } + tasks.withType().configureEach { + kotlinOptions { + jvmTarget = AndroidConfig.JavaVersion.toString() + // freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" + // freeCompilerArgs += "-Xcontext-receivers" + // Treat all Kotlin warnings as errors (disabled by default) + // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties + // val warningsAsErrors: String? by project + // allWarningsAsErrors = warningsAsErrors.toBoolean() + } + } + dependencies { + "coreLibraryDesugaring"(libs.desugar) + } +} + +internal fun Project.configureCompose(commonExtension: CommonExtension<*, *, *, *, *, *>) { + pluginManager.apply(kotlinx.plugins.compose.compiler.get().pluginId) + + commonExtension.apply { + buildFeatures { + compose = true + } + + dependencies { + "implementation"(platform(compose.bom)) + } + } + + extensions.configure { + featureFlags.set(setOf(ComposeFeatureFlag.OptimizeNonSkippingGroups)) + + val enableMetrics = project.providers.gradleProperty("enableComposeCompilerMetrics").orNull.toBoolean() + val enableReports = project.providers.gradleProperty("enableComposeCompilerReports").orNull.toBoolean() + + val rootBuildDir = rootProject.layout.buildDirectory.asFile.get() + val relativePath = projectDir.relativeTo(rootDir) + + if (enableMetrics) { + rootBuildDir.resolve("compose-metrics").resolve(relativePath).let(metricsDestination::set) + } + + if (enableReports) { + rootBuildDir.resolve("compose-reports").resolve(relativePath).let(reportsDestination::set) + } + } +} + +internal fun Project.configureTest() { + tasks.withType { + useJUnitPlatform() + testLogging { + events(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED) + } + } +} diff --git a/core/build.gradle.kts b/core/build.gradle.kts index e169090b2b..c8fa08982e 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,8 +1,8 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - alias(androidx.plugins.library) - alias(kotlinx.plugins.multiplatform) + id("yokai.android.library") + kotlin("multiplatform") alias(kotlinx.plugins.serialization) } diff --git a/data/build.gradle.kts b/data/build.gradle.kts index e4d4542e3d..6f17a84c4b 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -1,7 +1,7 @@ plugins { - alias(kotlinx.plugins.multiplatform) + id("yokai.android.library") + kotlin("multiplatform") alias(kotlinx.plugins.serialization) - alias(androidx.plugins.library) alias(libs.plugins.sqldelight) } diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index 6c31e4bfb9..e2f0e2da78 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -1,7 +1,7 @@ plugins { - alias(kotlinx.plugins.multiplatform) + id("yokai.android.library") + kotlin("multiplatform") alias(kotlinx.plugins.serialization) - alias(androidx.plugins.library) } kotlin { diff --git a/gradle/androidx.versions.toml b/gradle/androidx.versions.toml index c65c235f27..efae61e57b 100644 --- a/gradle/androidx.versions.toml +++ b/gradle/androidx.versions.toml @@ -4,6 +4,8 @@ agp = "8.7.3" lifecycle = "2.8.7" [libraries] +gradle = { module = "com.android.tools.build:gradle", version.ref = "agp" } + activity = { module = "androidx.activity:activity-ktx", version.ref = "activity" } activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity" } annotation = { module = "androidx.annotation:annotation", version = "1.9.1" } diff --git a/gradle/kotlinx.versions.toml b/gradle/kotlinx.versions.toml index 9fcc9e314c..afeeadc0fe 100644 --- a/gradle/kotlinx.versions.toml +++ b/gradle/kotlinx.versions.toml @@ -4,6 +4,9 @@ serialization = "1.7.3" xml_serialization = "0.90.3" [libraries] +gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +compose-compiler-gradle = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" } + coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version = "1.10.1" } coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android" } coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core" } @@ -26,4 +29,4 @@ android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } -parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } +parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize" } diff --git a/i18n/build.gradle.kts b/i18n/build.gradle.kts index 3879a5b92e..6cf146d185 100644 --- a/i18n/build.gradle.kts +++ b/i18n/build.gradle.kts @@ -2,8 +2,8 @@ import yokai.build.generatedBuildDir import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - alias(kotlinx.plugins.multiplatform) - alias(androidx.plugins.library) + id("yokai.android.library") + kotlin("multiplatform") alias(libs.plugins.moko) } diff --git a/presentation/core/build.gradle.kts b/presentation/core/build.gradle.kts index 2dd788bcb9..bb2b8d8303 100644 --- a/presentation/core/build.gradle.kts +++ b/presentation/core/build.gradle.kts @@ -1,6 +1,7 @@ plugins { - alias(androidx.plugins.library) - alias(kotlinx.plugins.android) + id("yokai.android.library") + id("yokai.android.library.compose") + kotlin("android") } android { @@ -12,6 +13,22 @@ android { } } +kotlin { + compilerOptions { + freeCompilerArgs.addAll( + "-opt-in=androidx.compose.animation.ExperimentalAnimationApi", + "-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi", + "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", + "-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi", + "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api", + "-opt-in=androidx.compose.ui.ExperimentalComposeUiApi", + "-opt-in=kotlinx.coroutines.FlowPreview", + ) + } +} + dependencies { api(libs.material) + + implementation(compose.bundles.compose) } diff --git a/presentation/widget/build.gradle.kts b/presentation/widget/build.gradle.kts index 4f4f4edb44..aa44817507 100644 --- a/presentation/widget/build.gradle.kts +++ b/presentation/widget/build.gradle.kts @@ -1,9 +1,9 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - alias(androidx.plugins.library) - alias(kotlinx.plugins.android) - alias(kotlinx.plugins.compose.compiler) + id("yokai.android.library") + id("yokai.android.library.compose") + kotlin("android") } android { diff --git a/source/api/build.gradle.kts b/source/api/build.gradle.kts index 8d6fe1986a..31f3f0856e 100644 --- a/source/api/build.gradle.kts +++ b/source/api/build.gradle.kts @@ -1,8 +1,8 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - alias(androidx.plugins.library) - alias(kotlinx.plugins.multiplatform) + id("yokai.android.library") + kotlin("multiplatform") alias(kotlinx.plugins.serialization) }