diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/AbstractCInteropCommonizerTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/AbstractCInteropCommonizerTask.kt index 58dc3e92441..55071e529fd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/AbstractCInteropCommonizerTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/AbstractCInteropCommonizerTask.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout.base64Hash import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout.ensureMaxFileNameLength import org.jetbrains.kotlin.commonizer.identityString +import org.jetbrains.kotlin.gradle.utils.changing import org.jetbrains.kotlin.gradle.utils.outputFilesProvider import java.io.File @@ -34,8 +35,10 @@ internal fun AbstractCInteropCommonizerTask.outputDirectory(group: CInteropCommo internal fun AbstractCInteropCommonizerTask.commonizedOutputLibraries(dependent: CInteropCommonizerDependent): FileCollection { return outputFilesProvider { - (commonizedOutputDirectory(dependent) ?: return@outputFilesProvider emptySet()) - .listFiles().orEmpty().toSet() + val outputDirectory = commonizedOutputDirectory(dependent) ?: return@outputFilesProvider emptySet() + project.providers.changing { + outputDirectory.listFiles().orEmpty().toSet() + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/providerApiUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/providerApiUtils.kt index 8c689816589..65ef1257102 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/providerApiUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/providerApiUtils.kt @@ -13,7 +13,10 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory import org.gradle.api.provider.SetProperty +import org.gradle.api.provider.ValueSource +import org.gradle.api.provider.ValueSourceParameters import java.io.File import kotlin.reflect.KProperty @@ -125,3 +128,41 @@ internal inline fun Project.listProperty(noinline itemsProvider: () internal inline fun Project.setProperty(noinline itemsProvider: () -> Iterable): SetProperty = objects.setProperty(T::class.java).apply { set(provider(itemsProvider)) } + +/** + * Changing Provider will be evaluated every time it accessed. + * + * And its producing [code] will be serilalised to Configuration Cache as is + * So that it still will be evaluated during Task Execution phase. + * It is very convenient for Configuration Cache compatibility. + * + * It is recommended to use Task Output's and map/flatMap them to other Task Inputs but in cases when TaskOutput's is not available + * as Gradle's Properties or Providers then this [changing] provider can be used. + * + * name `changing` and overall concept is borrowed from Gradle internal API [org.gradle.api.internal.provider.Providers.changing] + * + * @see org.gradle.api.internal.provider.ChangingProvider + */ +internal fun ProviderFactory.changing(code: () -> T): Provider { + @Suppress("UNCHECKED_CAST") + val adhocValueSourceClass = AdhocValueSource::class.java as Class> + return of(adhocValueSourceClass) { valueSourceSpec -> + valueSourceSpec.parameters { + it.producingLambda.set(code) + } + } +} + +private abstract class AdhocValueSource : ValueSource { + + // this interface can't be parameterized with T since it breaks internal Gradle logic + // This is why producingLambda is '() -> Any?' but not '() -> T' + interface Parameters : ValueSourceParameters { + val producingLambda: Property<() -> Any?> + } + + override fun obtain(): T { + @Suppress("UNCHECKED_CAST") + return parameters.producingLambda.get().invoke() as T + } +} \ No newline at end of file