Skip to content

Commit

Permalink
Migrate decompose progress di activityholder modules to KMP (#860)
Browse files Browse the repository at this point in the history
**Background**

Continue migration to KMP - core:progress, core:di, core:ui:decompose
core:activityholder

Also added custom gradle plugin to create dependencies with named scopes
aka `commonMainDependencies` `dekstopMainDependencies`

**Changes**

- Refactored modules to support KMP
- Added dependencies gradle plugin
- Replace `kotlin.sourceSets.xxxMain.dependencies` to `xxxDependencies`
- Move `:core:ktx:android-jre` into sharedJvmMain
- Added build-konfig module to support KMP constants flags

**Test plan**

Green CI/CD
  • Loading branch information
makeevrserg authored May 28, 2024
1 parent d214311 commit 3287a46
Show file tree
Hide file tree
Showing 60 changed files with 433 additions and 162 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/internal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
uses: gradle/gradle-build-action@4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff # v3
with:
cache-read-only: false
arguments: testDebug detekt lint
arguments: testDebugUnitTest desktopTest detekt lint
build_number:
name: Generate build number
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
- name: Unit test
uses: gradle/gradle-build-action@4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff # v3
with:
arguments: testDebug
arguments: testDebugUnitTest desktopTest
detekt:
name: "Check project by detekt"
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# 1.6.10 - In Progress

-
- [KMP] Migration core:activityholder, core:di, core:progpress, core:ui:decompose

# 1.6.9

Expand Down
10 changes: 10 additions & 0 deletions build-logic/plugins/convention/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
`kotlin-dsl`
id("java-gradle-plugin")
}

dependencies {
Expand All @@ -17,3 +18,12 @@ dependencies {

implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
}

gradlePlugin {
plugins {
create("flipper.multiplatform-dependencies") {
id = name
implementationClass = "com.flipperdevices.buildlogic.plugin.FlipperMultiplatformDependenciesPlugin"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.flipperdevices.buildlogic

import com.flipperdevices.buildlogic.model.FlavorType
import org.gradle.api.Project

object ApkConfig {
Expand Down Expand Up @@ -49,6 +50,21 @@ object ApkConfig {

val Project.IS_SENTRY_ENABLED
get() = prop("is_metric_enabled", true).toBoolean()

val Project.CURRENT_FLAVOR_TYPE: FlavorType
get() {
val default = FlavorType.DEV
val key = "CURRENT_FLAVOR_TYPE"
val propValue = propOrNull(key)
if (propValue == null) {
logger.warn("Property $key was not found, writing default $default")
}
return FlavorType.values().find { it.name == propValue } ?: default
}
}

internal fun Project.propOrNull(key: String): String? {
return providers.gradleProperty(key).orNull
}

internal fun Project.prop(key: String, default: Any): String {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.flipperdevices.buildlogic.model

/**
* This enum is used to define new kotlin-generated BuildKonfig
*
* We already have multiple flavors for android - debug, internal, release
* but android's flavor BuildConfig generation isn't compatible with KMP,
* so in the end, when project will e KMP-full, this will be final version
* of BuildKonfig field values
*/
enum class FlavorType(val isLogEnabled: Boolean) {
DEV(isLogEnabled = true),
PROD(isLogEnabled = false)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.flipperdevices.buildlogic.plugin

import com.flipperdevices.buildlogic.util.ProjectExt.kotlin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.create

class FlipperMultiplatformDependenciesPlugin : Plugin<Project> {
override fun apply(target: Project) {
target.kotlin.sourceSets.forEach { sourceSet ->
val fullSourceSetName = sourceSet.name
val noMainSourceSetName = if (fullSourceSetName.endsWith(MAIN_SOURCE_SET_POSTFIX)) {
fullSourceSetName.replace(
oldValue = MAIN_SOURCE_SET_POSTFIX,
newValue = ""
)
} else {
fullSourceSetName
}

target.extensions.create(
"${noMainSourceSetName}Dependencies",
FlipperMultiplatformDependenciesScope::class,
target,
fullSourceSetName
)
}
}

companion object {
/**
* The postfix of default source set naming aka commonMain, androidMain etc
*/
private const val MAIN_SOURCE_SET_POSTFIX = "Main"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.flipperdevices.buildlogic.plugin

import com.flipperdevices.buildlogic.util.ProjectExt.kotlin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler

open class FlipperMultiplatformDependenciesScope(
project: Project,
name: String
) : KotlinDependencyHandler by DefaultKotlinDependencyHandler(
parent = project.kotlin.sourceSets.getByName(name),
project = project
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.flipperdevices.buildlogic.util

import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension

internal object ProjectExt {
/**
* Required to remove gradle.kotlin.dsl.accessors dependency
*/
val Project.kotlin: KotlinMultiplatformExtension
get() {
val extensionAware = (this as org.gradle.api.plugins.ExtensionAware)
val kotlinExtension = extensionAware.extensions.getByName("kotlin")
return kotlinExtension as KotlinMultiplatformExtension
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,27 @@ kotlin {
jvm("desktop")

sourceSets {
val desktopMain by getting
val commonMain by getting

/**
* We shouldn't create sources, which is named as original targets sourcesets.
*
* As an example - jvm() target will create sourceSet jvmMain - and we would have conflicts
* with our create jvmMain sourceSet
*
* This is the reason to name it `jvmSharedMain`
*/
val jvmSharedMain by creating {
dependsOn(commonMain)
}

val androidMain by getting {
dependsOn(jvmSharedMain)
}

val desktopMain by getting {
dependsOn(jvmSharedMain)
}

androidMain.dependencies {
implementation(libs.compose.tooling)
Expand All @@ -36,5 +56,22 @@ kotlin {
desktopMain.dependencies {
implementation(compose.desktop.currentOs)
}

// Testing
val commonTest by getting

val jvmSharedTest by creating {
dependsOn(commonTest)
}

@Suppress("UnusedPrivateProperty")
val androidUnitTest by getting {
dependsOn(jvmSharedTest)
}

@Suppress("UnusedPrivateProperty")
val desktopTest by getting {
dependsOn(jvmSharedTest)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,50 @@ kotlin {
jvm("desktop")

sourceSets {
val desktopMain by getting
val commonMain by getting

/**
* We shouldn't create sources, which is named as original targets sourcesets.
*
* As an example - jvm() target will create sourceSet jvmMain - and we would have conflicts
* with our create jvmMain sourceSet
*
* This is the reason to name it `jvmSharedMain`
*/
val jvmSharedMain by creating {
dependsOn(commonMain)
}

val androidMain by getting {
dependsOn(jvmSharedMain)
}

val desktopMain by getting {
dependsOn(jvmSharedMain)
}

androidMain.dependencies {
}
commonMain.dependencies {
}
desktopMain.dependencies {
}

// Testing
val commonTest by getting

val jvmSharedTest by creating {
dependsOn(commonTest)
}

@Suppress("UnusedPrivateProperty")
val androidUnitTest by getting {
dependsOn(jvmSharedTest)
}

@Suppress("UnusedPrivateProperty")
val desktopTest by getting {
dependsOn(jvmSharedTest)
}
}
}
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ plugins {
id("flipper.lint")
alias(libs.plugins.android.test) apply false
alias(libs.plugins.baselineprofile) apply false
alias(libs.plugins.buildkonfig) apply false
}
5 changes: 3 additions & 2 deletions components/core/activityholder/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
plugins {
id("flipper.android-lib")
id("flipper.multiplatform")
id("flipper.multiplatform-dependencies")
}

android.namespace = "com.flipperdevices.core.activityholder"

dependencies {
androidDependencies {
implementation(libs.appcompat)
}
19 changes: 19 additions & 0 deletions components/core/build-konfig/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import com.flipperdevices.buildlogic.ApkConfig.CURRENT_FLAVOR_TYPE

plugins {
id("flipper.multiplatform")
id("flipper.multiplatform-dependencies")
alias(libs.plugins.buildkonfig)
}

group = "com.flipperdevices.core.buildkonfig"

android.namespace = "$group"

buildConfig {
className("BuildKonfig")
packageName("$group")
useKotlinOutput { internalVisibility = false }
buildConfigField(String::class.java, "PACKAGE", "$group")
buildConfigField(Boolean::class.java, "IS_LOG_ENABLED", CURRENT_FLAVOR_TYPE.isLogEnabled)
}
21 changes: 9 additions & 12 deletions components/core/data/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
plugins {
id("flipper.multiplatform")
id("flipper.multiplatform-dependencies")
}

android.namespace = "com.flipperdevices.core.data"

kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.kotlin.immutable.collections)
implementation(libs.compose.ui)
}
commonDependencies {
implementation(libs.kotlin.immutable.collections)
implementation(libs.compose.ui)
}

commonTest.dependencies {
implementation(libs.junit)
implementation(libs.mockito.kotlin)
implementation(libs.ktx.testing)
}
}
commonTestDependencies {
implementation(libs.junit)
implementation(libs.mockito.kotlin)
implementation(libs.ktx.testing)
}
10 changes: 8 additions & 2 deletions components/core/di/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
plugins {
id("flipper.android-lib")
id("flipper.multiplatform")
id("flipper.multiplatform-dependencies")
}

android.namespace = "com.flipperdevices.core.di"

dependencies {
commonDependencies {
implementation(libs.dagger)
}

jvmSharedTestDependencies {
implementation(libs.junit)
implementation(libs.kotlin.coroutines.test)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@file:Suppress("FunctionNaming")

package com.flipperdevices.core.di

import org.junit.Assert
import org.junit.Test

/**
* This is a sample test class to demonstrate how to use jvmSharedTest source set
*/
class ComponentHolderJvmSharedSampleTest {
@Test
fun GIVEN_empty_holder_WHEN_taking_int_class_THEN_throws() {
Assert.assertThrows(Throwable::class.java) {
ComponentHolder.component<Int>()
}
}
}
Loading

0 comments on commit 3287a46

Please sign in to comment.