From e937f0739b1a95f69e8ea56013613881bd082fe0 Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Wed, 24 May 2023 11:17:40 +0200 Subject: [PATCH] [Gradle] Process project dependencies in CLI version of CInterop[MDT]Task If MetadataDependencyTransformation is triggered it will resolve related metadata dependency configuration. Which is not recommended from gradle performance point of view. Update CInterop[MDT]Task to work as regular [MDT]Task i.e. it will process project dependencies during task execution but keep the original functionality for IDE. Since during IDE import it is expected to resolve configurations during gradle configuration phase. ^KT-58471 Verification Pending --- .../CInteropMetadataDependencyClasspath.kt | 40 +++++++++----- ...ropMetadataDependencyTransformationTask.kt | 52 ++++++++++--------- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyClasspath.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyClasspath.kt index b8620a54364..77eccc9e744 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyClasspath.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyClasspath.kt @@ -35,21 +35,33 @@ internal fun Project.createCInteropMetadataDependencyClasspath(sourceSet: Defaul else locateOrRegisterCInteropMetadataDependencyTransformationTask(sourceSet) if (dependencyTransformationTask == null) return project.files() - /* - The classpath will be assembled by three independent parts - 1) C-Interop Metadata which will be downloaded Jar files that get transformed by the transformation task - 2) C-Interop Metadata directly provided by dependency projects (in the same build) - 3) C-Interop Metadata from 'associated compilations' / additionalVisible source sets - (e.g. 'nativeTest' will be able to access the classpath from 'nativeMain') - */ - return project.files(dependencyTransformationTask.map { it.outputLibraryFiles }) + - createCInteropMetadataDependencyClasspathFromProjectDependencies(sourceSet, forIde) + - createCInteropMetadataDependencyClasspathFromAssociatedCompilations(sourceSet, forIde) + val dependencyTransformationTaskOutputs = project.files(dependencyTransformationTask.map { it.outputLibraryFiles }) + return if (forIde) { + /* + For IDE Import the classpath will be assembled by three independent parts: + 1) C-Interop Metadata which will be downloaded Jar files that get transformed by the transformation task + 2) C-Interop Metadata directly provided by dependency projects (in the same build) + 3) C-Interop Metadata from 'associated compilations' / additionalVisible source sets + (e.g. 'nativeTest' will be able to access the classpath from 'nativeMain') + */ + dependencyTransformationTaskOutputs + + createCInteropMetadataDependencyClasspathFromProjectDependenciesForIde(sourceSet) + + createCInteropMetadataDependencyClasspathFromAssociatedCompilations(sourceSet, true) + } else { + /* + For CLI execution the classpath will be assembled from two parts: + 1) C-Interop metadata from the transformation task which transforms + Project Dependencies and External Module Dependencies (e.g. the ones that downloaded from maven repo) + 2) C-Interop Metadata from 'associated compilations' / additionalVisible source sets + (e.g. 'nativeTest' will be able to access the classpath from 'nativeMain') + */ + dependencyTransformationTaskOutputs + + createCInteropMetadataDependencyClasspathFromAssociatedCompilations(sourceSet, false) + } } -private fun Project.createCInteropMetadataDependencyClasspathFromProjectDependencies( - sourceSet: DefaultKotlinSourceSet, - forIde: Boolean +private fun Project.createCInteropMetadataDependencyClasspathFromProjectDependenciesForIde( + sourceSet: DefaultKotlinSourceSet ): FileCollection { return filesProvider { sourceSet.metadataTransformation @@ -63,7 +75,7 @@ private fun Project.createCInteropMetadataDependencyClasspathFromProjectDependen } chooseVisibleSourceSets.visibleSourceSetProvidingCInterops?.let { visibleSourceSetName -> - projectMetadataProvider.getSourceSetCInteropMetadata(visibleSourceSetName, if (forIde) Ide else Cli) + projectMetadataProvider.getSourceSetCInteropMetadata(visibleSourceSetName, Ide) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyTransformationTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyTransformationTask.kt index ed1d39ba8d9..4f998df1800 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyTransformationTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyTransformationTask.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.utils.filesProvider import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.project.model.KpmModuleIdentifier +import org.jetbrains.kotlin.utils.addToStdlib.applyIf import java.io.File import java.io.Serializable import java.util.concurrent.Callable @@ -55,7 +56,9 @@ internal fun Project.locateOrRegisterCInteropMetadataDependencyTransformationTas /* outputDirectory = */ project.layout.kotlinTransformedCInteropMetadataLibraryDirectoryForBuild(sourceSet.name), /* cleaning = */ - CInteropMetadataDependencyTransformationTask.Cleaning.DeleteOutputDirectory + CInteropMetadataDependencyTransformationTask.Cleaning.DeleteOutputDirectory, + /* skipProjectDependencies = */ + false, // we want project dependencies to be included in the output ), configureTask = { configureTaskOrder(); onlyIfSourceSetIsSharedNative() } ) @@ -81,7 +84,9 @@ internal fun Project.locateOrRegisterCInteropMetadataDependencyTransformationTas /* outputDirectory = */ project.kotlinTransformedCInteropMetadataLibraryDirectoryForIde, /* cleaning = */ - CInteropMetadataDependencyTransformationTask.Cleaning.None + CInteropMetadataDependencyTransformationTask.Cleaning.None, + /* skipProjectDependencies = */ + true, ), configureTask = { configureTaskOrder(); onlyIfSourceSetIsSharedNative() } ) @@ -121,7 +126,6 @@ internal open class CInteropMetadataDependencyTransformationTask @Inject constru private val parameters = GranularMetadataTransformation.Params(project, sourceSet) - sealed class Cleaning : Serializable { abstract fun cleanOutputDirectory(outputDirectory: File) @@ -168,32 +172,32 @@ internal open class CInteropMetadataDependencyTransformationTask @Inject constru private fun materializeMetadata( chooseVisibleSourceSets: ChooseVisibleSourceSets - ): List = when (chooseVisibleSourceSets.metadataProvider) { - /* Nothing to transform: We will use original commonizer output in such cases */ - is ProjectMetadataProvider -> emptyList() - - /* Extract/Materialize all cinterop files from composite jar file */ - is ArtifactMetadataProvider -> chooseVisibleSourceSets.metadataProvider.read { artifactContent -> - val visibleSourceSetName = chooseVisibleSourceSets.visibleSourceSetProvidingCInterops ?: return emptyList() - val sourceSetContent = artifactContent.findSourceSet(visibleSourceSetName) ?: return emptyList() - sourceSetContent.cinteropMetadataBinaries - .onEach { cInteropMetadataBinary -> cInteropMetadataBinary.copyIntoDirectory(outputDirectory) } - .map { cInteropMetadataBinary -> outputDirectory.resolve(cInteropMetadataBinary.relativeFile) } - } - } - - private fun Configuration.withoutProjectDependencies(): FileCollection { - return incoming.artifactView { view -> - view.componentFilter { componentIdentifier -> - componentIdentifier !is ProjectComponentIdentifier + ): Iterable { + val metadataProvider = chooseVisibleSourceSets.metadataProvider + return when (metadataProvider) { + is ProjectMetadataProvider -> { + if (skipProjectDependencies) return emptyList() + val visibleSourceSetName = chooseVisibleSourceSets.visibleSourceSetProvidingCInterops ?: return emptyList() + metadataProvider + .getSourceSetCInteropMetadata(visibleSourceSetName, ProjectMetadataProvider.MetadataConsumer.Cli) + ?.files + .orEmpty() } - }.files + + /* Extract/Materialize all cinterop files from composite jar file */ + is ArtifactMetadataProvider -> metadataProvider.read { artifactContent -> + val visibleSourceSetName = chooseVisibleSourceSets.visibleSourceSetProvidingCInterops ?: return emptyList() + val sourceSetContent = artifactContent.findSourceSet(visibleSourceSetName) ?: return emptyList() + sourceSetContent.cinteropMetadataBinaries + .onEach { cInteropMetadataBinary -> cInteropMetadataBinary.copyIntoDirectory(outputDirectory) } + .map { cInteropMetadataBinary -> outputDirectory.resolve(cInteropMetadataBinary.relativeFile) } + } + } } private fun Iterable.resolutionsToTransform(): List { return filterIsInstance() - /* We do not care about Project to Project dependencies: Those shall use the commonizer output directly (no transformation) */ - .filter { it.dependency.id !is ProjectComponentIdentifier } + .applyIf(skipProjectDependencies) { filter { it.dependency.id !is ProjectComponentIdentifier } } } }