[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
This commit is contained in:
Anton Lakotka
2023-05-24 11:17:40 +02:00
committed by Space Team
parent 72c7d15be8
commit e937f0739b
2 changed files with 54 additions and 38 deletions
@@ -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)
}
}
}
@@ -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<File> = 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<File> {
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<MetadataDependencyResolution>.resolutionsToTransform(): List<ChooseVisibleSourceSets> {
return filterIsInstance<ChooseVisibleSourceSets>()
/* 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 } }
}
}