Skip to content

Commit 4d319da

Browse files
committed
Improved KMP expect/actual bindings on Android
1 parent f70216f commit 4d319da

31 files changed

Lines changed: 344 additions & 164 deletions

File tree

build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ plugins {
66
alias(libs.plugins.kotlin.android) apply false
77
alias(libs.plugins.kotlin.jvm) apply false
88
alias(libs.plugins.kotlin.multiplatform) apply false
9-
alias(libs.plugins.android) apply false
9+
alias(libs.plugins.android.application) apply false
10+
alias(libs.plugins.android.library) apply false
1011
alias(libs.plugins.publicationsReport)
1112
`jacoco-report-aggregation`
1213
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask
2+
import com.android.build.gradle.internal.lint.LintModelWriterTask
3+
import com.github.gmazzo.buildconfig.BuildConfigTask
4+
5+
plugins {
6+
alias(libs.plugins.android.library)
7+
alias(libs.plugins.kotlin.android)
8+
id("com.github.gmazzo.buildconfig")
9+
}
10+
11+
java.toolchain.languageVersion = JavaLanguageVersion.of(libs.versions.java.get())
12+
13+
android {
14+
namespace = "com.github.gmazzo.buildconfig.demos.android.lib"
15+
compileSdk = 36
16+
17+
buildFeatures.buildConfig = true
18+
19+
compileOptions {
20+
targetCompatibility(java.targetCompatibility)
21+
sourceCompatibility(java.sourceCompatibility)
22+
}
23+
24+
// mimics the variant-aware buildConfigField behavior from Android, by declaring fields on the final variant sourceSet
25+
libraryVariants.all variant@{
26+
buildConfig.sourceSets.named(this@variant.name) {
27+
className.set("BuildConfig")
28+
29+
buildConfigField("APP_NAME", project.name)
30+
buildConfigField("APP_SECRET", "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu")
31+
buildConfigField("BUILD_TIME", System.currentTimeMillis())
32+
buildConfigField("FEATURE_ENABLED", true)
33+
buildConfigField("MAGIC_NUMBERS", intArrayOf(1, 2, 3, 4))
34+
35+
buildConfigField<Boolean>("IS_DEBUG", this@variant.buildType.isDebuggable)
36+
buildConfigField<String>("BRAND", this@variant.flavorName)
37+
}
38+
}
39+
}
40+
41+
dependencies {
42+
testImplementation(testFixtures(projects.demoProject.groovy))
43+
}
44+
45+
// workaround of AGP issue failing to pick test sources correctly
46+
tasks.withType<AndroidLintAnalysisTask>().configureEach {
47+
mustRunAfter(tasks.withType<BuildConfigTask>())
48+
}
49+
tasks.withType<LintModelWriterTask>().configureEach {
50+
mustRunAfter(tasks.withType<BuildConfigTask>())
51+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<manifest/>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.github.gmazzo.buildconfig.demos.kts_android_lib
2+
3+
import com.github.gmazzo.buildconfig.demos.android.lib.BuildConfig as AndroidBuildConfig
4+
import com.github.gmazzo.buildconfig.demos.groovy.BuildConfigBaseTest
5+
6+
class BuildConfigTest : BuildConfigBaseTest() {
7+
8+
override fun extraCases() = arrayOf(
9+
// properties cases
10+
arrayOf("com.github.gmazzo.buildconfig.demos.android.lib", AndroidBuildConfig.LIBRARY_PACKAGE_NAME),
11+
12+
arrayOf("kts-android-lib", BuildConfig.APP_NAME),
13+
arrayOf("Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu", BuildConfig.APP_SECRET),
14+
arrayOf(true, System.currentTimeMillis() >= BuildConfig.BUILD_TIME),
15+
arrayOf(true, BuildConfig.FEATURE_ENABLED),
16+
arrayOf(listOf(1, 2, 3, 4), BuildConfig.MAGIC_NUMBERS.toList()),
17+
18+
// variant cases
19+
arrayOf(AndroidBuildConfig.DEBUG, BuildConfig.IS_DEBUG),
20+
)
21+
22+
}

demo-project/kts-android/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import com.android.build.gradle.internal.lint.LintModelWriterTask
33
import com.github.gmazzo.buildconfig.BuildConfigTask
44

55
plugins {
6-
alias(libs.plugins.android)
6+
alias(libs.plugins.android.application)
77
alias(libs.plugins.kotlin.android)
88
id("com.github.gmazzo.buildconfig")
99
}

demo-project/kts-multiplatform/build.gradle.kts

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import com.squareup.kotlinpoet.TypeSpec
77

88
plugins {
99
alias(libs.plugins.kotlin.multiplatform)
10-
alias(libs.plugins.android)
10+
alias(libs.plugins.android.application)
1111
id("com.github.gmazzo.buildconfig")
1212
}
1313

@@ -25,10 +25,21 @@ kotlin {
2525

2626
android {
2727
compileSdk = 36
28-
namespace = "com.github.gmazzo.buildconfig.demos.kts_multiplatform"
28+
namespace = "com.github.gmazzo.buildconfig.demos.android"
29+
buildFeatures.buildConfig = true
30+
defaultConfig.minSdk = 21
31+
32+
flavorDimensions += listOf("brand", "env")
33+
productFlavors {
34+
create("stage") { dimension = "env" }
35+
create("prod") { dimension = "env" }
36+
create("bar") { dimension = "brand" }
37+
create("foo") { dimension = "brand" }
38+
}
2939
}
3040

3141
dependencies {
42+
commonMainImplementation(libs.uriKMP)
3243
commonTestImplementation(libs.kotlin.test)
3344
}
3445

@@ -37,29 +48,53 @@ buildConfig {
3748
buildConfigField("IS_MOBILE", expect(false)) // with a default
3849
buildConfigField("PLATFORM", expect<String>()) // without a default
3950
buildConfigField("DEBUG", expect(false)) // to be changed by an Android variant
51+
buildConfigField("com.eygraber.uri.Uri", "ENDPOINT", expect(expression("Uri.parse(\"https://api.example.com\")")))
52+
buildConfigField("PRODUCT_VALUE", expect<String?>(null))
53+
54+
forClass("i18n") {
55+
useKotlinOutput { topLevelConstants = true }
56+
57+
buildConfigField("i18n_hello", "Hello")
58+
buildConfigField("i18n_kind", expect<String>())
59+
}
4060

4161
sourceSets.named("androidMain") {
4262
buildConfigField("PLATFORM", "android")
4363
buildConfigField("IS_MOBILE", true)
4464
buildConfigField("ANDROID_VALUE", "anAndroidValue")
65+
forClass("i18n").buildConfigField("i18n_kind", "android")
4566
}
4667

4768
sourceSets.named("androidDebug") {
4869
buildConfigField("DEBUG", true)
4970
}
5071

72+
sourceSets.named("androidStage") {
73+
buildConfigField("com.eygraber.uri.Uri", "ENDPOINT", expression("Uri.parse(\"https://stage.api.example.com\")"))
74+
}
75+
76+
sourceSets.named("androidFoo") {
77+
buildConfigField<String?>("PRODUCT_VALUE", "fooValue")
78+
}
79+
80+
sourceSets.named("androidBar") {
81+
buildConfigField<String?>("PRODUCT_VALUE", "barValue")
82+
}
83+
5184
sourceSets.named("jvmMain") {
5285
buildConfigField("PLATFORM", "jvm")
5386
buildConfigField("JVM_VALUE", "aJvmValue")
87+
forClass("i18n").buildConfigField("i18n_kind", "jvm")
5488
}
5589

5690
sourceSets.named("iosMain") {
5791
buildConfigField("PLATFORM", "ios")
5892
buildConfigField("IS_MOBILE", true)
5993
buildConfigField("IOS_VALUE", "anIOSValue")
94+
forClass("i18n").buildConfigField("i18n_kind", "ios")
6095
}
6196

62-
sourceSets.named("jsMain") {
97+
sourceSets.named("webMain") {
6398
// Customize the generator to add @JsName annotations to the generated object
6499
generator = object : BuildConfigKotlinGenerator() {
65100
override fun adaptSpec(spec: TypeSpec) = spec.toBuilder()
@@ -71,6 +106,10 @@ buildConfig {
71106
.build()
72107
}
73108

109+
forClass("i18n").buildConfigField("i18n_kind", "web")
110+
}
111+
112+
sourceSets.named("jsMain") {
74113
buildConfigField("PLATFORM", "js")
75114
buildConfigField("JS_VALUE", "aJsValue")
76115
}

demo-project/kts-multiplatform/src/androidUnitTest/kotlin/com/github/gmazzo/buildconfig/demos/kts_multiplatform/BuildConfigTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.gmazzo.buildconfig.demos.kts_multiplatform
22

3+
import com.github.gmazzo.buildconfig.demos.android.BuildConfig as AndroidBuildConfig
34
import kotlin.test.Test
45
import kotlin.test.assertEquals
56

@@ -9,6 +10,7 @@ class BuildConfigTest {
910
fun testBuildConfigProperties() {
1011
assertEquals("android", BuildConfig.PLATFORM)
1112
assertEquals(true, BuildConfig.IS_MOBILE)
13+
assertEquals(AndroidBuildConfig.DEBUG, BuildConfig.DEBUG)
1214
assertEquals("aCommonValue", BuildConfig.COMMON_VALUE)
1315
assertEquals("anAndroidValue", BuildConfig.ANDROID_VALUE)
1416
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package com.github.gmazzo.buildconfig.demos.kts_multiplatform
2+
3+
actual val expected_i18n_kind = "android"

demo-project/kts-multiplatform/src/commonTest/kotlin/com/github/gmazzo/buildconfig/demos/kts_multiplatform/CommonBuildConfigTest.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,10 @@ class CommonBuildConfigTest {
1010
assertEquals("aCommonValue", BuildConfig.COMMON_VALUE)
1111
}
1212

13+
@Test
14+
fun testI18nProperties() {
15+
assertEquals("Hello", i18n_hello)
16+
assertEquals(expected_i18n_kind, i18n_kind)
17+
}
18+
1319
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package com.github.gmazzo.buildconfig.demos.kts_multiplatform
2+
3+
expect val expected_i18n_kind: String

0 commit comments

Comments
 (0)