[Gradle] NativeDistributionCommonizationCache: Support associative commonization

^KT-47301
This commit is contained in:
sebastian.sellmair
2021-06-17 13:25:26 +02:00
committed by Space
parent 21cef41ba5
commit 73ffc0d180
5 changed files with 47 additions and 22 deletions
@@ -8,7 +8,10 @@ package org.jetbrains.kotlin.gradle
import org.gradle.internal.os.OperatingSystem import org.gradle.internal.os.OperatingSystem
import org.jetbrains.kotlin.gradle.internals.DISABLED_NATIVE_TARGETS_REPORTER_WARNING_PREFIX import org.jetbrains.kotlin.gradle.internals.DISABLED_NATIVE_TARGETS_REPORTER_WARNING_PREFIX
import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories
import kotlin.test.* import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import kotlin.test.fail
class CommonizerIT : BaseGradleIT() { class CommonizerIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired = GradleVersionRequired.FOR_MPP_SUPPORT override val defaultGradleVersion: GradleVersionRequired = GradleVersionRequired.FOR_MPP_SUPPORT
@@ -17,26 +20,30 @@ class CommonizerIT : BaseGradleIT() {
private const val commonizerOutput = "Preparing commonized Kotlin/Native libraries" private const val commonizerOutput = "Preparing commonized Kotlin/Native libraries"
} }
@Ignore // TODO NOW
@Test @Test
fun `test commonizeNativeDistributionWithIosLinuxWindows`() { fun `test commonizeNativeDistributionWithIosLinuxWindows`() {
with(Project("commonizeNativeDistributionWithIosLinuxWindows")) { with(Project("commonizeNativeDistributionWithIosLinuxWindows")) {
build(":p1:commonize", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=false") { build(":cleanNativeDistributionCommonization") {
assertTasksExecuted(":p1:commonizeNativeDistribution") assertSuccessful()
}
build("commonize", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=false") {
assertTasksExecuted(":commonizeNativeDistribution")
assertContains(DISABLED_NATIVE_TARGETS_REPORTER_WARNING_PREFIX) assertContains(DISABLED_NATIVE_TARGETS_REPORTER_WARNING_PREFIX)
assertContains(commonizerOutput) assertContains(commonizerOutput)
assertSuccessful() assertSuccessful()
} }
build(":p1:commonize", "--rerun-tasks", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=true") { build("commonize", "--rerun-tasks", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=true") {
assertTasksExecuted(":p1:commonizeNativeDistribution") assertTasksExecuted(":commonizeNativeDistribution")
assertContains("Native Distribution Commonization: Cache hit") assertContains("Native Distribution Commonization: Cache hit")
assertContains("Native Distribution Commonization: All available targets are commonized already")
assertNotContains(commonizerOutput) assertNotContains(commonizerOutput)
assertSuccessful() assertSuccessful()
} }
build(":p1:commonize", "--rerun-tasks", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=false") { build("commonize", "--rerun-tasks", "-Pkotlin.mpp.enableNativeDistributionCommonizationCache=false") {
assertTasksExecuted(":p1:commonizeNativeDistribution") assertTasksExecuted(":commonizeNativeDistribution")
assertContains("Native Distribution Commonization: Cache disabled") assertContains("Native Distribution Commonization: Cache disabled")
assertContains(commonizerOutput) assertContains(commonizerOutput)
assertSuccessful() assertSuccessful()
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.native.internal
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.internal.isInIdeaSync import org.jetbrains.kotlin.gradle.internal.isInIdeaSync
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
@@ -98,7 +99,7 @@ internal val Project.commonizeNativeDistributionHierarchicallyTask: TaskProvider
if (!isHierarchicalCommonizationEnabled) return null if (!isHierarchicalCommonizationEnabled) return null
return rootProject.locateOrRegisterTask( return rootProject.locateOrRegisterTask(
"commonizeNativeDistribution", "commonizeNativeDistribution",
invokeWhenRegistered = { commonizeTask.dependsOn(this) }, invokeWhenRegistered = { rootProject.commonizeTask.dependsOn(this); cleanNativeDistributionCommonizationTask },
configureTask = { configureTask = {
group = "interop" group = "interop"
description = "Invokes the commonizer on platform libraries provided by the Kotlin/Native distribution" description = "Invokes the commonizer on platform libraries provided by the Kotlin/Native distribution"
@@ -106,6 +107,19 @@ internal val Project.commonizeNativeDistributionHierarchicallyTask: TaskProvider
) )
} }
internal val Project.cleanNativeDistributionCommonizationTask: TaskProvider<Delete>?
get() {
val commonizeNativeDistributionTask = commonizeNativeDistributionHierarchicallyTask ?: return null
return rootProject.locateOrRegisterTask(
"cleanNativeDistributionCommonization",
configureTask = {
group = "interop"
description = "Deletes all previously commonized klib's from the Kotlin/Native distribution"
delete(commonizeNativeDistributionTask.map { it.getRootOutputDirectory() })
}
)
}
private inline fun <reified T : Task> Project.locateOrRegisterTask( private inline fun <reified T : Task> Project.locateOrRegisterTask(
name: String, name: String,
args: List<Any> = emptyList(), args: List<Any> = emptyList(),
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
import org.jetbrains.kotlin.gradle.targets.metadata.getMetadataCompilationForSourceSet import org.jetbrains.kotlin.gradle.targets.metadata.getMetadataCompilationForSourceSet
import org.jetbrains.kotlin.gradle.utils.filesProvider import org.jetbrains.kotlin.gradle.utils.filesProvider
import java.io.File
internal fun Project.setUpHierarchicalKotlinNativePlatformDependencies() { internal fun Project.setUpHierarchicalKotlinNativePlatformDependencies() {
val kotlin = multiplatformExtensionOrNull ?: return val kotlin = multiplatformExtensionOrNull ?: return
@@ -35,12 +36,12 @@ internal fun Project.getNativeDistributionDependencies(target: CommonizerTarget)
} }
private fun Project.getOriginalPlatformLibrariesFor(target: LeafCommonizerTarget): FileCollection { private fun Project.getOriginalPlatformLibrariesFor(target: LeafCommonizerTarget): FileCollection {
return project.filesProvider { konanDistribution.platformLibsDir.resolve(target.konanTarget.name).listFiles().orEmpty().toSet() } return project.filesProvider { konanDistribution.platformLibsDir.resolve(target.konanTarget.name).listLibraryFiles().toSet() }
} }
private fun HierarchicalNativeDistributionCommonizerTask.getCommonizedPlatformLibrariesFor(target: SharedCommonizerTarget): FileCollection { private fun HierarchicalNativeDistributionCommonizerTask.getCommonizedPlatformLibrariesFor(target: SharedCommonizerTarget): FileCollection {
val targetOutputDirectory = CommonizerOutputFileLayout.resolveCommonizedDirectory(getRootOutputDirectory(), target) val targetOutputDirectory = CommonizerOutputFileLayout.resolveCommonizedDirectory(getRootOutputDirectory(), target)
return project.filesProvider { targetOutputDirectory.listFiles().orEmpty().toList() }.builtBy(this) return project.filesProvider { targetOutputDirectory.listLibraryFiles() }.builtBy(this)
} }
private fun HierarchicalNativeDistributionCommonizerTask.getCommonizedDependenciesFor(target: CommonizerTarget): FileCollection { private fun HierarchicalNativeDistributionCommonizerTask.getCommonizedDependenciesFor(target: CommonizerTarget): FileCollection {
@@ -64,3 +65,6 @@ private fun Project.addDependencies(sourceSet: KotlinSourceSet, libraries: FileC
private val Project.konanDistribution: KonanDistribution private val Project.konanDistribution: KonanDistribution
get() = KonanDistribution(project.file(konanHome)) get() = KonanDistribution(project.file(konanHome))
private fun File.listLibraryFiles(): List<File> = listFiles().orEmpty()
.filter { it.isDirectory || it.extension == "klib" }
@@ -29,7 +29,6 @@ internal class NativeDistributionCommonizationCache(
) { ) {
if (!project.isNativeDistributionCommonizationCacheEnabled) { if (!project.isNativeDistributionCommonizationCacheEnabled) {
logInfo("Cache disabled") logInfo("Cache disabled")
return commonizer.commonizeNativeDistribution(konanHome, outputDirectory, outputTargets, logLevel)
} }
val cachedOutputTargets = outputTargets val cachedOutputTargets = outputTargets
@@ -37,25 +36,26 @@ internal class NativeDistributionCommonizationCache(
.onEach { outputTarget -> logInfo("Cache hit: $outputTarget already commonized") } .onEach { outputTarget -> logInfo("Cache hit: $outputTarget already commonized") }
.toSet() .toSet()
val missingOutputTargets = outputTargets - cachedOutputTargets val enqueuedOutputTargets = if (project.isNativeDistributionCommonizationCacheEnabled) outputTargets - cachedOutputTargets
else outputTargets
if (canReturnFast(konanHome, missingOutputTargets)) { if (canReturnFast(konanHome, enqueuedOutputTargets)) {
logInfo("All available targets are commonized already - Nothing to do") logInfo("All available targets are commonized already - Nothing to do")
return return
} }
missingOutputTargets enqueuedOutputTargets
.map { outputTarget -> resolveCommonizedDirectory(outputDirectory, outputTarget) } .map { outputTarget -> resolveCommonizedDirectory(outputDirectory, outputTarget) }
.forEach { commonizedDirectory -> if (commonizedDirectory.exists()) commonizedDirectory.deleteRecursively() } .forEach { commonizedDirectory -> if (commonizedDirectory.exists()) commonizedDirectory.deleteRecursively() }
commonizer.commonizeNativeDistribution( commonizer.commonizeNativeDistribution(
konanHome, outputDirectory, missingOutputTargets, logLevel konanHome, outputDirectory, enqueuedOutputTargets, logLevel
) )
missingOutputTargets enqueuedOutputTargets
.map { outputTarget -> resolveCommonizedDirectory(outputDirectory, outputTarget) } .map { outputTarget -> resolveCommonizedDirectory(outputDirectory, outputTarget) }
.filter { commonizedDirectory -> commonizedDirectory.isDirectory } .filter { commonizedDirectory -> commonizedDirectory.isDirectory }
.forEach { commonizedDirectory -> commonizedDirectory.resolve(".success").isFile } .forEach { commonizedDirectory -> commonizedDirectory.resolve(".success").createNewFile() }
} }
private fun isCached(directory: File): Boolean { private fun isCached(directory: File): Boolean {
@@ -46,11 +46,11 @@ internal fun commonizeTarget(
inputs: TargetDependent<CirTreeRoot?>, inputs: TargetDependent<CirTreeRoot?>,
output: CommonizerTarget output: CommonizerTarget
): CirRootNode? { ): CirRootNode? {
parameters.logger.progress(output, "Commonized declarations from ${inputs.targets}") { val availableTrees = inputs.filterNonNull()
val availableTrees = inputs.filterNonNull() /* Nothing to merge */
/* Nothing to merge */ if (availableTrees.size == 0) return null
if (availableTrees.size == 0) return null
parameters.logger.progress(output, "Commonized declarations from ${inputs.targets}") {
val classifiers = CirKnownClassifiers( val classifiers = CirKnownClassifiers(
commonizedNodes = CirCommonizedClassifierNodes.default(), commonizedNodes = CirCommonizedClassifierNodes.default(),
commonDependencies = parameters.dependencyClassifiers(output) commonDependencies = parameters.dependencyClassifiers(output)