diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CommonizerIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CommonizerIT.kt index cc91eca2c91..ca3663ecdce 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CommonizerIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CommonizerIT.kt @@ -168,25 +168,32 @@ open class CommonizerIT : KGPBaseTest() { @DisplayName("Commonize Curl Interop copy CommonizeCInterop for Ide") @GradleTest - fun testCommonizeCurlInteropcopyCommonizeCInteropForIde(gradleVersion: GradleVersion) { + fun testCommonizeCurlInteropcopyCommonizeCInteropForIde( + gradleVersion: GradleVersion, + @TempDir tempDir: Path, + ) { nativeProject("commonizeCurlInterop", gradleVersion) { configureCommonizerTargets() - val expectedOutputDirectoryForIde = projectPath.resolve(".kotlin/commonizer") + fun expectedOutputDirectoryForIde(): Path = tempDir + .resolve("projects-1") + .findInPath("commonizer") ?: throw IllegalStateException("Failed to find 'commonizer' directory!") + val expectedOutputDirectoryForBuild = projectPath.resolve("build/classes/kotlin/commonizer") - build(":copyCommonizeCInteropForIde") { + build(":copyCommonizeCInteropForIde", "-Pkotlin.user.home=${tempDir.absolutePathString()}") { assertTasksExecuted(":cinteropCurlTargetB") assertTasksExecuted(":commonizeCInterop") - assertDirectoryExists(expectedOutputDirectoryForIde, "Missing output directory for IDE") + val commonizerIdeOutput = expectedOutputDirectoryForIde() + assertDirectoryExists(commonizerIdeOutput, "Missing output directory for IDE") assertDirectoryExists(expectedOutputDirectoryForBuild, "Missing output directory for build") - assertEqualDirectories(expectedOutputDirectoryForBuild.toFile(), expectedOutputDirectoryForIde.toFile(), false) + assertEqualDirectories(expectedOutputDirectoryForBuild.toFile(), commonizerIdeOutput.toFile(), false) } - build(":clean") { - assertDirectoryExists(expectedOutputDirectoryForIde, "Expected ide output directory to survive cleaning") + build(":clean", "-Pkotlin.user.home=${tempDir.absolutePathString()}") { + assertDirectoryExists(expectedOutputDirectoryForIde(), "Expected ide output directory to survive cleaning") assertFileNotExists(expectedOutputDirectoryForBuild, "Expected output directory for build to be cleaned") } } @@ -535,23 +542,28 @@ open class CommonizerIT : KGPBaseTest() { @DisplayName("KT-58223 test commonized libraries for IDE can be stored in different data dir") @GradleTest - fun testCommonizedLibrariesForIDECanBeStoredInDifferentDir(gradleVersion: GradleVersion) { + fun testCommonizedLibrariesForIDECanBeStoredInDifferentDir( + gradleVersion: GradleVersion, + @TempDir tempDir: Path, + ) { nativeProject("commonizeCurlInterop", gradleVersion) { - gradleProperties.append("kotlin.persistent.gradle.data.dir=.kotlin_custom") + gradleProperties.append("kotlin.persistent.gradle.data.dir=${tempDir.absolutePathString()}") configureCommonizerTargets() - val expectedOutputDirectoryForIde = projectPath.resolve(".kotlin_custom/commonizer") + fun expectedOutputDirectoryForIde(): Path = tempDir + .resolve("projects-1") + .findInPath("commonizer") ?: throw IllegalStateException("Failed to find 'commonizer' directory!") build(":copyCommonizeCInteropForIde") { assertTasksExecuted(":cinteropCurlTargetB") assertTasksExecuted(":commonizeCInterop") - assertDirectoryExists(expectedOutputDirectoryForIde, "Missing output directory for IDE") + assertDirectoryExists(expectedOutputDirectoryForIde(), "Missing output directory for IDE") } build(":clean") { - assertDirectoryExists(expectedOutputDirectoryForIde, "Expected ide output directory to survive cleaning") + assertDirectoryExists(expectedOutputDirectoryForIde(), "Expected ide output directory to survive cleaning") } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt index 8f42100faa1..9c3f0d8bf73 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt @@ -189,8 +189,15 @@ class MppIdeDependencyResolutionIT : KGPBaseTest() { } @GradleTest - fun `test cinterops - are stored in root gradle folder`(gradleVersion: GradleVersion) { - project(projectName = "cinteropImport", gradleVersion = gradleVersion) { + fun `test cinterops - are stored in root gradle folder`( + gradleVersion: GradleVersion, + @TempDir tempDir: Path, + ) { + project( + projectName = "cinteropImport", + gradleVersion = gradleVersion, + buildOptions = defaultBuildOptions.copy(kotlinUserHome = tempDir) + ) { resolveIdeDependencies("dep-with-cinterop") { dependencies -> /* Check behaviour of platform cinterops on linuxX64Main */ @@ -198,12 +205,12 @@ class MppIdeDependencyResolutionIT : KGPBaseTest() { .filter { !it.isNativeDistribution && it.klibExtra?.isInterop == true } .ifEmpty { fail("Expected at least one cinterop on linuxX64Main") } + val persistentCInteropsCache = tempDir.inProjectsPersistentCache("kotlinCInteropLibraries") cinterops.forEach { cinterop -> if (cinterop.classpath.isEmpty()) fail("Missing classpath for $cinterop") cinterop.classpath.forEach { cinteropFile -> /* Check file was copied into root .gradle folder */ - val expectedParent = projectPath.toFile().resolve(".gradle/kotlin/kotlinCInteropLibraries").canonicalFile - assertEquals(expectedParent, cinteropFile.parentFile.canonicalFile) + assertEquals(persistentCInteropsCache.toFile().canonicalFile, cinteropFile.parentFile.canonicalFile) /* Check crc in file name */ val crc = CRC32() 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 9a46ce1e85c..bd4278822e3 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 @@ -7,8 +7,8 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Project import org.gradle.api.file.ProjectLayout -import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.utils.compositeBuildRootProject +import org.jetbrains.kotlin.gradle.utils.kotlinMetadataDir import java.io.File private const val kotlinTransformedMetadataLibraries = "kotlinTransformedMetadataLibraries" @@ -18,23 +18,20 @@ private const val kotlinTransformedCInteropMetadataLibraries = "kotlinTransforme internal fun ProjectLayout.kotlinTransformedMetadataLibraryDirectoryForBuild(sourceSetName: String): File = buildDirectory.get().asFile.resolve(kotlinTransformedMetadataLibraries).resolve(sourceSetName) -internal val Project.kotlinGradleDataDirCompat - get() = kotlinPropertiesProvider.kotlinPersistentGradleDataDir ?: ".kotlin" - internal val Project.kotlinTransformedMetadataLibraryDirectoryForIde: File - get() = compositeBuildRootProject.rootDir - .resolve(project.kotlinGradleDataDirCompat) + get() = compositeBuildRootProject + .kotlinMetadataDir .resolve(kotlinTransformedMetadataLibraries) internal fun ProjectLayout.kotlinTransformedCInteropMetadataLibraryDirectoryForBuild(sourceSetName: String): File = buildDirectory.get().asFile.resolve(kotlinTransformedCInteropMetadataLibraries).resolve(sourceSetName) internal val Project.kotlinCInteropLibraryDirectoryForIde: File - get() = compositeBuildRootProject.rootDir - .resolve(project.kotlinGradleDataDirCompat) + get() = compositeBuildRootProject + .kotlinMetadataDir .resolve(kotlinCInteropLibraries) internal val Project.kotlinTransformedCInteropMetadataLibraryDirectoryForIde: File - get() = compositeBuildRootProject.rootDir - .resolve(project.kotlinGradleDataDirCompat) + get() = compositeBuildRootProject + .kotlinMetadataDir .resolve(kotlinTransformedCInteropMetadataLibraries) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CopyCInteropCommonizerTaskOutputForIdeTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CopyCInteropCommonizerTaskOutputForIdeTask.kt index c0ea050e0a5..76e87ee6c22 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CopyCInteropCommonizerTaskOutputForIdeTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CopyCInteropCommonizerTaskOutputForIdeTask.kt @@ -15,8 +15,8 @@ import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.compilerRunner.addBuildMetricsForTaskAction import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter +import org.jetbrains.kotlin.gradle.utils.kotlinMetadataDir import org.jetbrains.kotlin.gradle.utils.property -import org.jetbrains.kotlin.gradle.plugin.mpp.kotlinGradleDataDirCompat import java.io.File import javax.inject.Inject @@ -33,8 +33,7 @@ internal abstract class CopyCommonizeCInteropForIdeTask @Inject constructor( commonizeCInteropTask.map { it.allOutputDirectories } @get:OutputDirectory - override val outputDirectory: File = project.rootDir - .resolve(project.kotlinGradleDataDirCompat) + override val outputDirectory: File = project.kotlinMetadataDir .resolve("commonizer") .resolve(project.path.removePrefix(":").replace(":", "/")) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/persistentCaches.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/persistentCaches.kt index 0c920e8a0c4..4be273ab764 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/persistentCaches.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/persistentCaches.kt @@ -15,6 +15,7 @@ private const val PROJECTS_CACHE_VERSION = 1 private const val PROJECTS_CACHE_NAME_FULL = "$PROJECTS_CACHE_NAME-$PROJECTS_CACHE_VERSION" private const val SESSIONS_DIR_NAME = "sessions" +private const val METADATA_DIR_NAME = "metadata" internal val Project.basePersistentDir get() = kotlinPropertiesProvider.kotlinPersistentGradleDataDir?.let { File(it) } @@ -23,6 +24,11 @@ internal val Project.basePersistentDir internal val Project.kotlinSessionsDir get() = basePersistentDir.resolve(PROJECTS_CACHE_NAME_FULL).resolve(rootDir.absolutePathMd5Hash()).resolve(SESSIONS_DIR_NAME) +internal val Project.kotlinMetadataDir + get() = basePersistentDir.projectSpecificCache(rootDir).resolve(METADATA_DIR_NAME) + private val md5Digest by lazy { MessageDigest.getInstance("MD5") } private fun File.absolutePathMd5Hash(): String = md5Digest.digest(absolutePath.toByteArray()).toHexString() + +private fun File.projectSpecificCache(projectRootDir: File) = resolve(PROJECTS_CACHE_NAME_FULL).resolve(projectRootDir.absolutePathMd5Hash()) diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CInteropMetadataDependencyTransformationTaskTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CInteropMetadataDependencyTransformationTaskTest.kt index 7ac5505fdca..d2a1abee40f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CInteropMetadataDependencyTransformationTaskTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CInteropMetadataDependencyTransformationTaskTest.kt @@ -11,6 +11,7 @@ import org.gradle.api.Project import org.gradle.api.internal.TaskInternal import org.gradle.testfixtures.ProjectBuilder import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.mpp.kotlinTransformedCInteropMetadataLibraryDirectoryForIde import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet import org.jetbrains.kotlin.gradle.targets.native.internal.locateOrRegisterCInteropMetadataDependencyTransformationTask import org.jetbrains.kotlin.gradle.targets.native.internal.locateOrRegisterCInteropMetadataDependencyTransformationTaskForIde @@ -135,14 +136,12 @@ class CInteropMetadataDependencyTransformationTaskTest : MultiplatformExtensionT nativeMain as DefaultKotlinSourceSet ) ?: fail("Expected transformation task registered for '$nativeMain'") val cinteropTransformationTask = cinteropTransformationTaskProvider.get() - val projectRootDir = rootDir return cinteropTransformationTask .outputs .files - .map { it.relativeTo(projectRootDir) } .toSet() - // common root directory where all transformations stored - .minus(File(".kotlin/kotlinTransformedCInteropMetadataLibraries")) + // Shared output directory itself is always present in every task output + .minus(kotlinTransformedCInteropMetadataLibraryDirectoryForIde) } suspend fun assertTasksOutputsDoesntIntersect(a: Project, b: Project) {