From fec9f9fe62ae2b4fab6381bf0f4eadaa467c974b Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Wed, 1 Feb 2023 10:32:29 +0100 Subject: [PATCH] [Gradle] IdePlatformCinteropDependencyResolver: Retain cinterops for IDE in .gradle ^KT-56337 Verification Pending --- .../IdePlatformCinteropDependencyResolver.kt | 25 +++++++++++- .../resolveCinteropDependency.kt | 5 +-- .../mpp/CompositeMetadataArtifactImpl.kt | 10 +---- .../mpp/KotlinMetadataLibraryDirectories.kt | 4 ++ .../kotlin/gradle/utils/checksumUtils.kt | 39 +++++++++++++++++++ 5 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/checksumUtils.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdePlatformCinteropDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdePlatformCinteropDependencyResolver.kt index b024c18feac..70eafbcf880 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdePlatformCinteropDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdePlatformCinteropDependencyResolver.kt @@ -11,17 +11,40 @@ import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport +import org.jetbrains.kotlin.gradle.plugin.mpp.kotlinCInteropLibraryDirectoryForIde import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet import org.jetbrains.kotlin.gradle.targets.native.internal.getPlatformCinteropDependenciesOrEmpty +import org.jetbrains.kotlin.gradle.utils.crc32ChecksumString +import java.io.File internal object IdePlatformCinteropDependencyResolver : IdeDependencyResolver, IdeDependencyResolver.WithBuildDependencies { override fun resolve(sourceSet: KotlinSourceSet): Set { if (sourceSet !is DefaultKotlinSourceSet) return emptySet() val project = sourceSet.project - val cinteropFiles = project.getPlatformCinteropDependenciesOrEmpty(sourceSet) + + val cinteropFiles = project.getPlatformCinteropDependenciesOrEmpty(sourceSet).map { file -> + project.copyCInteropFileForIdeIfNecessary(file) + } + return project.resolveCInteropDependencies(cinteropFiles) } + /** + * Copies the file into a directory specifically for the IDE, so it survives ./gradlew clean + */ + private fun Project.copyCInteropFileForIdeIfNecessary(file: File): File { + if (!file.exists()) return file + val newFileName = "${file.nameWithoutExtension}-${file.crc32ChecksumString()}.${file.extension}" + val outputFile = kotlinCInteropLibraryDirectoryForIde.resolve(newFileName) + + /* Copy only if really necessary */ + if (!outputFile.exists()) { + file.copyTo(outputFile) + } + + return outputFile + } + override fun dependencies(project: Project): Iterable { return project.kotlinExtension.sourceSets.mapNotNull { sourceSet -> if (sourceSet !is DefaultKotlinSourceSet) return@mapNotNull null diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/resolveCinteropDependency.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/resolveCinteropDependency.kt index fac6b34365a..e5935a7568a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/resolveCinteropDependency.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/resolveCinteropDependency.kt @@ -6,15 +6,14 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers import org.gradle.api.Project -import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.gradle.idea.tcs.* import org.jetbrains.kotlin.gradle.idea.tcs.extras.klibExtra import org.jetbrains.kotlin.gradle.plugin.ide.KlibExtra import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.library.* -internal fun Project.resolveCInteropDependencies(cinteropFiles: FileCollection): Set { - return cinteropFiles.files +internal fun Project.resolveCInteropDependencies(cinteropFiles: Iterable): Set { + return cinteropFiles .filter { it.isDirectory || it.extension == KLIB_FILE_EXTENSION } .mapNotNull { libraryFile -> this.createCinteropLibraryDependency(libraryFile) } .toSet() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataArtifactImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataArtifactImpl.kt index dd874963965..f74974354f8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataArtifactImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataArtifactImpl.kt @@ -5,15 +5,13 @@ package org.jetbrains.kotlin.gradle.plugin.mpp +import org.jetbrains.kotlin.gradle.utils.checksumString import org.jetbrains.kotlin.gradle.utils.copyPartially import org.jetbrains.kotlin.gradle.utils.ensureValidZipDirectoryPath import org.jetbrains.kotlin.gradle.utils.listDescendants import java.io.Closeable import java.io.File import java.io.IOException -import java.nio.ByteBuffer -import java.util.* -import java.util.Base64.Encoder import java.util.zip.CRC32 import java.util.zip.ZipEntry import java.util.zip.ZipFile @@ -192,10 +190,6 @@ internal class CompositeMetadataArtifactImpl( */ private class ArtifactFile(private val file: File) : Closeable { - companion object { - val checksumStringEncoder: Encoder = Base64.getUrlEncoder().withoutPadding() - } - private var isClosed = false private val lazyZip = lazy { @@ -212,7 +206,7 @@ internal class CompositeMetadataArtifactImpl( val checksum: String by lazy(LazyThreadSafetyMode.NONE) { val crc32 = CRC32() entries.forEach { entry -> crc32.update(entry.crc.toInt()) } - checksumStringEncoder.encodeToString(ByteBuffer.allocate(4).putInt(crc32.value.toInt()).array()) + checksumString(crc32.value.toInt()) } /** diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataLibraryDirectories.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataLibraryDirectories.kt index ee8a0a83491..7d51b3ac748 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataLibraryDirectories.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataLibraryDirectories.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.gradle.utils.compositeBuildRootProject import java.io.File private const val kotlinTransformedMetadataLibraries = "kotlinTransformedMetadataLibraries" +private const val kotlinCInteropLibraries = "kotlinCInteropLibraries" private const val kotlinTransformedCInteropMetadataLibraries = "kotlinTransformedCInteropMetadataLibraries" internal fun ProjectLayout.kotlinTransformedMetadataLibraryDirectoryForBuild(sourceSetName: String): File = @@ -22,5 +23,8 @@ internal val Project.kotlinTransformedMetadataLibraryDirectoryForIde: File internal fun ProjectLayout.kotlinTransformedCInteropMetadataLibraryDirectoryForBuild(sourceSetName: String): File = buildDirectory.get().asFile.resolve(kotlinTransformedCInteropMetadataLibraries).resolve(sourceSetName) +internal val Project.kotlinCInteropLibraryDirectoryForIde: File + get() = compositeBuildRootProject.rootDir.resolve(".gradle").resolve("kotlin").resolve(kotlinCInteropLibraries) + internal val Project.kotlinTransformedCInteropMetadataLibraryDirectoryForIde: File get() = compositeBuildRootProject.rootDir.resolve(".gradle").resolve("kotlin").resolve(kotlinTransformedCInteropMetadataLibraries) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/checksumUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/checksumUtils.kt new file mode 100644 index 00000000000..53aa1b5f0d5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/checksumUtils.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.utils + +import java.io.BufferedInputStream +import java.io.File +import java.nio.ByteBuffer +import java.util.* +import java.util.zip.CRC32 + +private val checksumStringEncoder: Base64.Encoder = Base64.getUrlEncoder().withoutPadding() + +internal fun File.crc32Checksum(): Int { + val crc32 = CRC32() + val buffer = ByteArray(2048) + BufferedInputStream(inputStream()).use { fileStream -> + while (true) { + val read = fileStream.read(buffer) + if (read < 0) break + crc32.update(buffer, 0, read) + } + } + return crc32.value.toInt() +} + +internal fun File.crc32ChecksumString(): String { + return checksumString(crc32Checksum()) +} + +internal fun checksumString(checksum: Int): String { + return checksumString(ByteBuffer.allocate(4).putInt(checksum).array()) +} + +internal fun checksumString(checksum: ByteArray): String { + return checksumStringEncoder.encodeToString(checksum) +}