From ff59c4861706f2ae216b080bb46ba69d627137d6 Mon Sep 17 00:00:00 2001 From: Oleksandr Karpovich Date: Tue, 3 Oct 2023 19:35:18 +0200 Subject: [PATCH] Fix configuration cache for `syncComposeResourcesForIos` (#3764) Currently when `org.gradle.configuration-cache=true` we have an error: > Configuration cache state could not be cached: field `resourceFiles` of task `:shared:syncComposeResourcesForIos` of type `org.jetbrains.compose.experimental.uikit.tasks.SyncComposeResourcesForIosTask`: error writing value of type 'org.gradle.api.internal.provider.TransformBackedProvider' Old description (can be ignored): _This PR attempts to fix it in SyncComposeResourcesForIosTask by wrapping inputs into providers. It seems that gradle configuration cache doesn't like some provider types produced by `.map`, `.zip`, `.orElse`, etc._ **Latest description:** With configuration cache enabled, gradle runs all `orElse` providers during configuration (I don't know why yet). We used to throw an exception in `orElse` which led to the crash. This PR refactors SyncComposeResourcesForIosTask so it doesn't throw an exception immediately in orElse, but postpones it to later step. --- .../tasks/SyncComposeResourcesForIosTask.kt | 25 +++++++++++++------ .../tests/integration/GradlePluginTest.kt | 14 +++++++---- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/uikit/tasks/SyncComposeResourcesForIosTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/uikit/tasks/SyncComposeResourcesForIosTask.kt index 01797f9f7a..8d4b7e7264 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/uikit/tasks/SyncComposeResourcesForIosTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/uikit/tasks/SyncComposeResourcesForIosTask.kt @@ -19,25 +19,34 @@ import kotlin.io.path.pathString import kotlin.io.path.relativeTo abstract class SyncComposeResourcesForIosTask : AbstractComposeIosTask() { - private fun missingTargetEnvAttributeError(attribute: String): Provider = - providers.provider { - error( - "Could not infer iOS target $attribute. Make sure to build " + - "via XCode (directly or via Kotlin Multiplatform Mobile plugin for Android Studio)") + + private fun Provider.orElseThrowMissingAttributeError(attribute: String): Provider { + val noProvidedValue = "__NO_PROVIDED_VALUE__" + return this.orElse(noProvidedValue).map { + if (it == noProvidedValue) { + error( + "Could not infer iOS target $attribute. Make sure to build " + + "via XCode (directly or via Kotlin Multiplatform Mobile plugin for Android Studio)") + } + it } + } @get:Input val xcodeTargetPlatform: Provider = providers.gradleProperty("compose.ios.resources.platform") .orElse(providers.environmentVariable("PLATFORM_NAME")) - .orElse(missingTargetEnvAttributeError("platform")) + .orElseThrowMissingAttributeError("platform") + @get:Input val xcodeTargetArchs: Provider> = providers.gradleProperty("compose.ios.resources.archs") .orElse(providers.environmentVariable("ARCHS")) - .orElse(missingTargetEnvAttributeError("architectures")) - .map { it.split(",", " ").filter { it.isNotBlank() } } + .orElseThrowMissingAttributeError("architectures") + .map { + it.split(",", " ").filter { it.isNotBlank() } + } @get:Input internal val iosTargets: SetProperty = objects.setProperty(IosTargetResources::class.java) diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt index 24a7d27f00..89cae4831e 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/GradlePluginTest.kt @@ -62,13 +62,18 @@ class GradlePluginTest : GradlePluginTestBase() { ) } + // We rely on this property to use gradle configuration cache in some tests. + // Enabling configuration cache unconditionally breaks out tests with gradle 7.3.3. + // Old comment: 'for some reason configuration cache + test kit + custom vars does not work' + private val GradleVersion.isAtLeastGradle8 + get() = this >= GradleVersion.version("8.0") + @Test fun iosResources() { Assumptions.assumeTrue(currentOS == OS.MacOS) val iosTestEnv = iosTestEnv() val testEnv = defaultTestEnvironment.copy( - // for some reason configuration cache + test kit + custom vars does not work - useGradleConfigurationCache = false, + useGradleConfigurationCache = TestProperties.gradleBaseVersionForTests.isAtLeastGradle8, additionalEnvVars = iosTestEnv.envVars ) @@ -91,8 +96,7 @@ class GradlePluginTest : GradlePluginTestBase() { Assumptions.assumeTrue(currentOS == OS.MacOS) val iosTestEnv = iosTestEnv() val testEnv = defaultTestEnvironment.copy( - // for some reason configuration cache + test kit + custom vars does not work - useGradleConfigurationCache = false, + useGradleConfigurationCache = TestProperties.gradleBaseVersionForTests.isAtLeastGradle8, additionalEnvVars = iosTestEnv.envVars ) with(testProject(TestProjects.iosMokoResources, testEnv)) { @@ -345,4 +349,4 @@ class GradlePluginTest : GradlePluginTestBase() { } return constructor.newInstance(socket, logger, {}) as RemoteConnection } -} \ No newline at end of file +}