Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup + version catalog plugin api draft #124

Merged
merged 2 commits into from
May 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions application/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ buildscript {
minSdk = 21,
targetSdk = 31,
compileSdk = 31,
kotlinVersion = embeddedKotlinVersion,
agpVersion = "7.4.2",
dataBinding = true,
extraPlugins = listOf(
"androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3",
"com.google.firebase:firebase-crashlytics-gradle:2.9.4",
"tools.forma.demo:dependencies",
libs.plugins.tools.forma.demo.dependencies.get().pluginId,
)
)
}
20 changes: 18 additions & 2 deletions application/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,26 @@ dependencyResolutionManagement {
create("libs") {
addLibrary("com.jakewharton.timber:timber:4.7.1")
addBundle("coil", "io.coil-kt:coil:$coilVersion", "io.coil-kt:coil-base:$coilVersion")
addPlugin( "tools.forma.demo:dependencies:0.0.1")
}
}
}

fun VersionCatalogBuilder.addPlugin(
groupArtifactVersion: String,
vararg dependencies: String,
nameGenerator: (String) -> String = ::defaultNameGenerator
) {
val (group, artifact, version) = groupArtifactVersion.split(":")
plugin(nameGenerator(groupArtifactVersion), "$group:$artifact").version { strictly(version) }
}

fun VersionCatalogBuilder.addBundle(
name: String,
vararg groupArtifactVersion: String,
nameGenerator: (String) -> String = ::defaultNameGenerator
): String {
) {
bundle(name, groupArtifactVersion.map { addLibrary(it, nameGenerator) })
return name
}

fun VersionCatalogBuilder.addLibrary(
Expand All @@ -50,6 +59,7 @@ fun VersionCatalogBuilder.addLibrary(
fun defaultNameGenerator(groupArtifactVersion: String) =
groupArtifactVersion
.split(":")
.verifyVersion()
.dropLast(1)
.fold(emptyList<String>()) { acc, s -> acc + s.split(".", "-") }
.filter { it !in filteredTokens }
Expand All @@ -60,3 +70,9 @@ fun defaultNameGenerator(groupArtifactVersion: String) =
// refer to this issue https://github.com/gradle/gradle/issues/18536
// tools.forma.dependencies are applied in buildscript {} block
includeBuild("../build-dependencies")

fun List<String>.verifyVersion(): List<String> {
// Very naive check if last string contains version
if (!last().last().isDigit()) throw IllegalArgumentException("Version is not specified")
return this
}
10 changes: 6 additions & 4 deletions build-dependencies/dependencies/src/main/kotlin/Tools.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@

import tools.forma.config.FormaConfigurationStore

val configuration = FormaConfigurationStore.configuration

object dataBinding {
val viewBinding = transitiveDeps(
"androidx.databinding:viewbinding:${FormaConfigurationStore.configuration.agpVersion}"
"androidx.databinding:viewbinding:${configuration.agpVersion}"
)

val runtime = transitiveDeps(
"androidx.databinding:databinding-runtime:${FormaConfigurationStore.configuration.agpVersion}"
"androidx.databinding:databinding-runtime:${configuration.agpVersion}"
)

val common = transitiveDeps(
"androidx.databinding:databinding-common:${FormaConfigurationStore.configuration.agpVersion}"
"androidx.databinding:databinding-common:${configuration.agpVersion}"
)

val adapters = transitiveDeps(
"androidx.databinding:databinding-adapters:${FormaConfigurationStore.configuration.agpVersion}"
"androidx.databinding:databinding-adapters:${configuration.agpVersion}"
)
}

10 changes: 10 additions & 0 deletions plugins/android/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@file:Suppress("UnstableApiUsage")

import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask

plugins {
id("org.gradle.kotlin.kotlin-dsl")
id("com.gradle.plugin-publish")
Expand All @@ -6,6 +10,12 @@ plugins {
group = "tools.forma"
version = "0.0.1"

tasks.named("compileKotlin", KotlinCompilationTask::class.java) {
compilerOptions {
freeCompilerArgs.add("-Xcontext-receivers")
}
}

dependencies {
implementation("com.android.tools.build:gradle:7.4.2")
implementation(embeddedKotlin("gradle-plugin"))
Expand Down
90 changes: 47 additions & 43 deletions plugins/android/src/main/java/androidProjectConfiguration.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
@file:Suppress("ObjectPropertyName")

import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.tasks.Delete
import org.gradle.kotlin.dsl.ScriptHandlerScope
import org.gradle.kotlin.dsl.embeddedKotlinVersion
import org.gradle.kotlin.dsl.repositories
import tools.forma.android.utils.register
import tools.forma.config.ConfigurationStore
import tools.forma.config.FormaConfiguration
import tools.forma.config.FormaConfigurationStore
import tools.forma.android.utils.register

// TODO: add docs for every fun param
/**
Expand All @@ -22,45 +22,49 @@ import tools.forma.android.utils.register
* @param mandatoryOwners is a flag that enables mandatory owners for all modules
* @param extraPlugins is a list of extra plugins that will be applied to project
*/

fun ScriptHandlerScope.androidProjectConfiguration(
project: Project,
minSdk: Int,
targetSdk: Int,
compileSdk: Int,
kotlinVersion: String,
kotlinVersion: String = embeddedKotlinVersion,
agpVersion: String,
repositories: RepositoryHandler.() -> Unit = {},
dataBinding: Boolean = false,
compose: Boolean = false,
javaVersionCompatibility: JavaVersion = JavaVersion.VERSION_1_8, // Java/Kotlin configuration
mandatoryOwners: Boolean = false,
extraPlugins: List<Any>
vectorDrawablesUseSupportLibrary: Boolean = false,
extraPlugins: List<String> = emptyList()
) {
Forma.buildScriptConfiguration(this, extraPlugins)
with(project) {
buildScriptConfiguration(this, extraPlugins)

/**
* Default Android project clean task implementation
*/
/**
* Default Android project clean task implementation
*/
with(project) {
tasks.register("clean", Delete::class) {
delete(project.buildDir)
}
}

val configuration = FormaConfiguration(
minSdk = minSdk,
targetSdk = targetSdk,
compileSdk = compileSdk,
// we don't need check properties for exist, we read it successfully in forma configuration
kotlinVersion = kotlinVersion,
agpVersion = agpVersion,
repositories = repositories,
dataBinding = dataBinding,
javaVersionCompatibility = javaVersionCompatibility,
mandatoryOwners = mandatoryOwners
)

Forma.store(configuration)
val configuration = FormaConfiguration(
minSdk = minSdk,
targetSdk = targetSdk,
compileSdk = compileSdk,
// we don't need check properties for exist, we read it successfully in forma configuration
kotlinVersion = kotlinVersion,
agpVersion = agpVersion,
repositories = repositories,
dataBinding = dataBinding,
javaVersionCompatibility = javaVersionCompatibility,
mandatoryOwners = mandatoryOwners,
compose = compose,
vectorDrawablesUseSupportLibrary = vectorDrawablesUseSupportLibrary
)

}
Forma.store(configuration)
}

@Deprecated("Old approach to configuration, use ScriptHandlerScope Extension")
Expand All @@ -76,6 +80,8 @@ fun Project.androidProjectConfiguration(
generateMissedManifests: Boolean = false,
javaVersionCompatibility: JavaVersion = JavaVersion.VERSION_1_8, // Java/Kotlin configuration
mandatoryOwners: Boolean = false,
compose: Boolean = false,
vectorDrawablesUseSupportLibrary: Boolean = true,
) {

/**
Expand All @@ -95,29 +101,27 @@ fun Project.androidProjectConfiguration(
repositories = repositories,
dataBinding = dataBinding,
javaVersionCompatibility = javaVersionCompatibility,
mandatoryOwners = mandatoryOwners
mandatoryOwners = mandatoryOwners,
compose = compose,
vectorDrawablesUseSupportLibrary = vectorDrawablesUseSupportLibrary
)

Forma.store(configuration)
}

val buildScriptConfiguration: ScriptHandlerScope.(List<Any>) -> Unit = { classpathDeps ->
// TODO pass repositories configuration
repositories {
google()
mavenCentral()
}
dependencies {
classpathDeps.forEach { classpath(it) }
}
}

/**
* Singleton project configuration store
* TODO remove
*/
object Forma {

val configuration: FormaConfiguration get() = FormaConfigurationStore.configuration

fun store(configuration: FormaConfiguration) = FormaConfigurationStore.store(configuration)

val buildScriptConfiguration: ScriptHandlerScope.(List<Any>) -> Unit = { classpathDeps ->
// TODO pass repositories configuration
repositories {
google()
mavenCentral()
}
dependencies {
classpathDeps.forEach { classpath(it) }
}
}
}
object Forma: ConfigurationStore<FormaConfiguration> by FormaConfigurationStore
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,27 @@ data class FormaConfiguration(
val kotlinVersion: String,
val agpVersion: String,
val repositories: RepositoryHandler.() -> Unit,
// Databinding is Application level feature, android_binary will be infering dataBinding flag, developers does not need to know about
val dataBinding: Boolean = false,
val compose: Boolean = false,
val vectorDrawablesUseSupportLibrary: Boolean = true,
val javaVersionCompatibility: JavaVersion = JavaVersion.VERSION_1_8, // Java/Kotlin configuration
// Databinding is Application level feature, android_binary will be inferring dataBinding flag, developers does not need to know about
val dataBinding: Boolean,
val compose: Boolean,
val vectorDrawablesUseSupportLibrary: Boolean,
val javaVersionCompatibility: JavaVersion, // Java/Kotlin configuration
val mandatoryOwners: Boolean
)

/**
* Singleton project configuration store
* Singleton project configuration store, used by internal plugins
*/
object FormaConfigurationStore {

object FormaConfigurationStore : ConfigurationStore<FormaConfiguration> {
private lateinit var _configuration: FormaConfiguration
val configuration: FormaConfiguration get() = _configuration
override val configuration: FormaConfiguration get() = _configuration

fun store(configuration: FormaConfiguration) {
override fun store(configuration: FormaConfiguration) {
_configuration = configuration
}
}

interface ConfigurationStore<T : Any> {
val configuration: T
fun store(configuration: T)
}