From 7165d15d59f5c01083b8ad9a37f3da7799c5569d Mon Sep 17 00:00:00 2001 From: Dmitrii Krasnov Date: Fri, 24 Nov 2023 16:18:23 +0100 Subject: [PATCH] [Gradle Native] Added Kotlin Native Provider to all native tasks This provider is a first step of "Kotlin Native Toolchain". This solves several problems: 1) Resolving K/N bundle during configuration phase -> now it happens during execution phase 2) Downloading K/N bundle with internal mechanisms -> now it uses Gradle dependency resolvers and Transform Artifact ^KT-58303 ^KT-52567 ^KT-49268 --- .../jetbrains/kotlin/gradle/BuildCacheIT.kt | 32 ++++ .../kotlin/gradle/BuildCacheRelocationIT.kt | 18 ++- .../native/KotlinNativeCompilerDownloadIT.kt | 144 ++++++++++++++++++ .../native/NativeDownloadAndPlatformLibsIT.kt | 11 ++ .../kotlin/gradle/testbase/TestVersions.kt | 2 +- .../kotlin/gradle/testbase/outputHelpers.kt | 25 +-- .../build.gradle.kts | 8 + .../native1/build.gradle.kts | 12 ++ .../native1/gradle.properties | 0 .../native1/src/nativeMain/kotlin/Main.kt | 8 + .../native2/build.gradle.kts | 13 ++ .../native2/gradle.properties | 0 .../native2/src/nativeMain/kotlin/Main.kt | 8 + .../settings.gradle.kts | 3 + .../native-simple-project/build.gradle.kts | 12 ++ .../src/nativeMain/kotlin/main.kt | 3 + .../compilerRunner/nativeToolRunners.kt | 17 ++- .../gradle/plugin/AbstractKotlinPlugin.kt | 1 + .../gradle/plugin/KotlinPluginWrapper.kt | 23 +++ .../gradle/plugin/PropertiesProvider.kt | 8 + .../native/KonanPropertiesBuildService.kt | 2 +- .../native/KotlinNativeTargetPreset.kt | 7 +- .../native/NativeCompilerDownloader.kt | 123 +++++++++------ .../internal/PlatformLibrariesGenerator.kt | 6 +- .../targets/native/tasks/KotlinNativeLink.kt | 60 ++++++-- .../targets/native/tasks/KotlinNativeTasks.kt | 57 +++++-- .../artifact/KotlinNativeLinkArtifactTask.kt | 31 +++- .../KotlinNativeBundleArtifactFormat.kt | 57 +++++++ .../native/toolchain/KotlinNativeProvider.kt | 110 +++++++++++++ .../toolchain/UnzipTransformationAction.kt | 59 +++++++ .../unitTests/KotlinNativeToolchainTest.kt | 39 +++++ .../kotlin/commonizer/utils/konanHome.kt | 3 - 32 files changed, 787 insertions(+), 115 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/KotlinNativeCompilerDownloadIT.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/gradle.properties create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/src/nativeMain/kotlin/Main.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/gradle.properties create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/src/nativeMain/kotlin/Main.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/settings.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-simple-project/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-simple-project/src/nativeMain/kotlin/main.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/KotlinNativeBundleArtifactFormat.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/KotlinNativeProvider.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/UnzipTransformationAction.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinNativeToolchainTest.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheIT.kt index 09b1657aefa..c3aafd27297 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheIT.kt @@ -20,7 +20,12 @@ import org.gradle.api.logging.LogLevel import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.report.BuildReportType import org.jetbrains.kotlin.gradle.testbase.* +import org.jetbrains.kotlin.gradle.util.capitalize +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.target.presetName import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path import kotlin.io.path.ExperimentalPathApi import kotlin.io.path.readText import kotlin.io.path.relativeTo @@ -144,6 +149,33 @@ class BuildCacheIT : KGPBaseTest() { } } + @DisplayName("Changing native toolchain location should not break build cache") + @GradleTest + fun testNativeToolchainWithBuildCache(gradleVersion: GradleVersion, @TempDir customNativeHomePath: Path) { + nativeProject("native-simple-project", gradleVersion) { + enableLocalBuildCache(localBuildCacheDir) + + val buildOptionsBeforeCaching = defaultBuildOptions.copy( + nativeOptions = super.defaultBuildOptions.nativeOptions.copy( + version = TestVersions.Kotlin.STABLE_RELEASE, + distributionDownloadFromMaven = true + ) + ) + val nativeCompileTask = ":compileKotlin${HostManager.host.presetName.capitalize()}" + build(nativeCompileTask, buildOptions = buildOptionsBeforeCaching) { + assertTasksPackedToCache(nativeCompileTask) + } + + val buildOptionsAfterCaching = buildOptionsBeforeCaching.copy( + konanDataDir = customNativeHomePath, + ) + + build("clean", nativeCompileTask, buildOptions = buildOptionsAfterCaching) { + assertTasksFromCache(nativeCompileTask) + } + } + } + //doesn't work for build history files approach @DisplayName("Restore from build cache should not break incremental compilation") @GradleTest diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheRelocationIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheRelocationIT.kt index 5ce44658d15..6f020b16a97 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheRelocationIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheRelocationIT.kt @@ -20,8 +20,13 @@ import org.gradle.api.logging.LogLevel import org.gradle.testkit.runner.BuildResult import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.testbase.* +import org.jetbrains.kotlin.gradle.util.capitalize +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.target.presetName import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.io.TempDir import java.io.File +import java.nio.file.Path import kotlin.io.path.* @DisplayName("Build cache relocation") @@ -204,9 +209,16 @@ class BuildCacheRelocationIT : KGPBaseTest() { @DisplayName("with native project") @GradleTest fun testRelocationNative(gradleVersion: GradleVersion) { + val buildOptionsBeforeCaching = defaultBuildOptions.copy( + nativeOptions = super.defaultBuildOptions.nativeOptions.copy( + version = TestVersions.Kotlin.STABLE_RELEASE, + distributionDownloadFromMaven = true + ) + ) val (firstProject, secondProject) = prepareTestProjects( "native-build-cache", - gradleVersion + gradleVersion, + buildOptions = buildOptionsBeforeCaching ) { val localRepoUri = it.projectPath.resolve("repo").toUri() it.subProject("build-cache-app").buildGradleKts.append( @@ -276,12 +288,12 @@ class BuildCacheRelocationIT : KGPBaseTest() { buildJdk: File? = null, additionalConfiguration: (TestProject) -> Unit = {} ): Pair { - val firstProject = project(projectName, gradleVersion, buildOptions, buildJdk = buildJdk) { + val firstProject = project(projectName, gradleVersion, buildOptions, buildJdk = buildJdk, forceOutput = true) { enableLocalBuildCache(localBuildCacheDir) additionalConfiguration(this) } - val secondProject = project(projectName, gradleVersion, buildOptions, buildJdk = buildJdk) { + val secondProject = project(projectName, gradleVersion, buildOptions, buildJdk = buildJdk, forceOutput = true) { enableLocalBuildCache(localBuildCacheDir) additionalConfiguration(this) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/KotlinNativeCompilerDownloadIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/KotlinNativeCompilerDownloadIT.kt new file mode 100644 index 00000000000..a1c85437cba --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/KotlinNativeCompilerDownloadIT.kt @@ -0,0 +1,144 @@ +/* + * 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.native + +import org.gradle.util.GradleVersion +import org.jetbrains.kotlin.gradle.testbase.* +import org.jetbrains.kotlin.gradle.testbase.TestVersions.Kotlin.STABLE_RELEASE +import org.jetbrains.kotlin.gradle.util.capitalize +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.target.presetName +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path +import kotlin.io.path.absolutePathString +import kotlin.io.path.appendText +import kotlin.test.assertContains + + +@DisplayName("This test class contains different scenarios with downloading Kotlin Native Compiler during build.") +@NativeGradlePluginTests +class KotlinNativeCompilerDownloadIT : KGPBaseTest() { + + private val currentPlatform = HostManager.platformName() + + private val nativeHostTargetName = HostManager.host.presetName + + private val UNPUCK_KONAN_FINISHED_LOG = + "Moving Kotlin/Native bundle from tmp directory" + + private val STABLE_VERSION_DIR_NAME = "kotlin-native-prebuilt-$currentPlatform-$STABLE_RELEASE" + + private val DOWNLOAD_KONAN_FINISHED_LOG = + "Download $STABLE_VERSION_DIR_NAME.${if (HostManager.hostIsMingw) "zip" else "tar.gz"} finished," + + override val defaultBuildOptions: BuildOptions + get() = super.defaultBuildOptions.copy( + nativeOptions = super.defaultBuildOptions.nativeOptions.copy( + version = STABLE_RELEASE, + distributionDownloadFromMaven = true + ) + ) + + @DisplayName("KT-58303: Kotlin Native must not be downloaded during configuration phase") + @GradleTest + fun shouldNotDownloadKotlinNativeOnConfigurationPhase(gradleVersion: GradleVersion, @TempDir konanTemp: Path) { + nativeProject( + "native-simple-project", + gradleVersion, + buildOptions = defaultBuildOptions.copy( + konanDataDir = konanTemp, + ), + ) { + build("help") { + assertOutputDoesNotContain(DOWNLOAD_KONAN_FINISHED_LOG) + assertOutputDoesNotContain(UNPUCK_KONAN_FINISHED_LOG) + assertOutputDoesNotContain("Please wait while Kotlin/Native") + } + } + } + + @DisplayName("KT-58303: Kotlin Native must be downloaded during execution phase") + @GradleTest + fun shouldDownloadKotlinNativeOnExecutionPhase(gradleVersion: GradleVersion, @TempDir konanTemp: Path) { + nativeProject( + "native-simple-project", + gradleVersion, + buildOptions = defaultBuildOptions.copy( + konanDataDir = konanTemp, + ), + ) { + build("assemble") { + assertOutputDoesNotContain(DOWNLOAD_KONAN_FINISHED_LOG) + assertOutputContains(UNPUCK_KONAN_FINISHED_LOG) + assertOutputDoesNotContain("Please wait while Kotlin/Native") + } + } + } + + @DisplayName("KT-58303: Downloading Kotlin Native on configuration phase(deprecated version)") + @GradleTest + fun shouldDownloadKotlinNativeOnConfigurationPhaseWithToolchainDisabled(gradleVersion: GradleVersion, @TempDir konanTemp: Path) { + nativeProject( + "native-simple-project", + gradleVersion, + buildOptions = defaultBuildOptions.copy( + konanDataDir = konanTemp, + freeArgs = listOf("-Pkotlin.native.toolchain.enabled=false"), + ), + ) { + build("assemble") { + assertOutputContains(DOWNLOAD_KONAN_FINISHED_LOG) + assertOutputContains("Please wait while Kotlin/Native") + } + } + } + + @DisplayName("Checking multi-module native project with different path to kotlin native compiler in each module") + @GradleTest + fun multiModuleProjectWithDifferentKotlinNativeCompilers(gradleVersion: GradleVersion, @TempDir customNativeHomePath: Path) { + nativeProject("native-multi-module-project", gradleVersion, configureSubProjects = true) { + val defaultKotlinNativeHomePath = + defaultBuildOptions.konanDataDir?.toAbsolutePath()?.normalize() + ?: error("Default konan data dir must be set in this test before overriding") + + // setting different konan home in different subprojects + subProject("native1").gradleProperties.appendKonanToGradleProperties(customNativeHomePath.absolutePathString()) + subProject("native2").gradleProperties.appendKonanToGradleProperties(defaultKotlinNativeHomePath.absolutePathString()) + + val buildOptions = defaultBuildOptions.copy( + konanDataDir = null, + ) + + build("assemble", buildOptions = buildOptions) { + + // check that in first project we use k/n from custom konan location + assertNativeTasksClasspath(":native1:compileKotlin${nativeHostTargetName.capitalize()}") { + val konanLibsPath = customNativeHomePath.resolve(STABLE_VERSION_DIR_NAME).resolve("konan").resolve("lib") + assertContains(it, konanLibsPath.resolve("kotlin-native-compiler-embeddable.jar").absolutePathString()) + assertContains(it, konanLibsPath.resolve("trove4j.jar").absolutePathString()) + } + + // check that in second project we use k/n from default konan location + assertNativeTasksClasspath(":native2:compileKotlin${nativeHostTargetName.capitalize()}") { + val konanLibsPath = defaultKotlinNativeHomePath.resolve(STABLE_VERSION_DIR_NAME).resolve("konan").resolve("lib") + assertContains(it, konanLibsPath.resolve("kotlin-native-compiler-embeddable.jar").absolutePathString()) + assertContains(it, konanLibsPath.resolve("trove4j.jar").absolutePathString()) + } + } + } + } + + private fun Path.appendKonanToGradleProperties(konanAbsolutePathString: String) { + this.appendText( + """ + + kotlin.native.home=${konanAbsolutePathString} + konan.data.dir=${konanAbsolutePathString} + """.trimIndent() + ) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt index c2b0ee4ec65..133da03fb7c 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeDownloadAndPlatformLibsIT.kt @@ -27,6 +27,15 @@ import kotlin.io.path.appendText ) @DisplayName("Tests for K/N builds with native downloading and platform libs") @NativeGradlePluginTests +@Deprecated( + message = + """ + This is deprecated test class with regression checks for old downloading logic. + We support it during migration to kotlin native toolchain. + If you want to add test here, be sure that you have added similar test with `-Pkotlin.native.toolchain.enabled=true`. + """, + ReplaceWith("NativeDownloadAndPlatformLibsIT") +) class NativeDownloadAndPlatformLibsIT : KGPBaseTest() { private val platformName: String = HostManager.platformName() @@ -34,6 +43,8 @@ class NativeDownloadAndPlatformLibsIT : KGPBaseTest() { override val defaultBuildOptions: BuildOptions get() = super.defaultBuildOptions.withBundledKotlinNative().copy( + // Disabling toolchain feature for checking stable logic with downloading kotlin native + freeArgs = listOf("-Pkotlin.native.toolchain.enabled=false"), // For each test in this class, we need to provide an isolated .konan directory, // so we create it within each test project folder konanDataDir = workingDir.resolve(".konan") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/TestVersions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/TestVersions.kt index 3882bcf4945..19aa1811df6 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/TestVersions.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/TestVersions.kt @@ -36,7 +36,7 @@ interface TestVersions { } object Kotlin { - const val STABLE_RELEASE = "1.9.20" + const val STABLE_RELEASE = "1.9.21" // Copied from KOTLIN_VERSION.kt file val CURRENT diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputHelpers.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputHelpers.kt index 2f6536c53ab..fe9b76f4676 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputHelpers.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputHelpers.kt @@ -62,17 +62,20 @@ fun getOutputForTask(taskPath: String, output: String, logLevel: LogLevel = LogL LogLevel.DEBUG -> taskOutputRegexForDebugLog(taskPath) else -> throw throw IllegalStateException("Unsupported log lever for task output was given: $logLevel") }) - .find(output) - ?.let { it.groupValues[1] } - ?: error( - """ - Could not find output for task $taskPath. - ================= - Build output is: - $output - ================= - """.trimIndent() - ) + .findAll(output) + .map { it.groupValues[1] } + .joinToString(System.lineSeparator()) + .ifEmpty { + error( + """ + Could not find output for task $taskPath. + ================= + Build output is: + $output + ================= + """.trimIndent() + ) + } class CommandLineArguments( val args: List, diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/build.gradle.kts new file mode 100644 index 00000000000..47f0a035a09 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + kotlin("multiplatform") apply false +} + +repositories { + mavenCentral() + mavenLocal() +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/build.gradle.kts new file mode 100644 index 00000000000..8e42be4db97 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + kotlin("multiplatform") +} + +repositories { + mavenLocal() + mavenCentral() +} + +kotlin { + () +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/gradle.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/src/nativeMain/kotlin/Main.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/src/nativeMain/kotlin/Main.kt new file mode 100644 index 00000000000..aa08577a39b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native1/src/nativeMain/kotlin/Main.kt @@ -0,0 +1,8 @@ +/* + * 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. + */ + +fun main() { + println("Hello from first") +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/build.gradle.kts new file mode 100644 index 00000000000..3e802aa605d --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + kotlin("multiplatform") +} + +repositories { + mavenLocal() + mavenCentral() +} + + +kotlin { + () +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/gradle.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/src/nativeMain/kotlin/Main.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/src/nativeMain/kotlin/Main.kt new file mode 100644 index 00000000000..79b8fa40dcd --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/native2/src/nativeMain/kotlin/Main.kt @@ -0,0 +1,8 @@ +/* + * 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. + */ + +fun main() { + println("Hello from second") +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/settings.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/settings.gradle.kts new file mode 100644 index 00000000000..c6bb3324138 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-multi-module-project/settings.gradle.kts @@ -0,0 +1,3 @@ +rootProject.name = "native-multi-module-project" +include("native1") +include("native2") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-simple-project/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-simple-project/build.gradle.kts new file mode 100644 index 00000000000..3416680867b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-simple-project/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + kotlin("multiplatform") +} + +repositories { + mavenCentral() + mavenLocal() +} + +kotlin { + () +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-simple-project/src/nativeMain/kotlin/main.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-simple-project/src/nativeMain/kotlin/main.kt new file mode 100644 index 00000000000..c97b641f50f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-simple-project/src/nativeMain/kotlin/main.kt @@ -0,0 +1,3 @@ +fun main() { + println("Hello from simple native project") +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt index 86acbb0f890..561b27e9213 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt @@ -32,10 +32,10 @@ import java.util.* private val Project.jvmArgs get() = PropertiesProvider(this).nativeJvmArgs?.split("\\s+".toRegex()).orEmpty() -internal val Project.konanHome: String - get() = PropertiesProvider(this).konanDataDir?.let { NativeCompilerDownloader(project).compilerDirectory.absolutePath } - ?: PropertiesProvider(this).nativeHome?.let { file(it).absolutePath } - ?: NativeCompilerDownloader(project).compilerDirectory.absolutePath +internal val Project.konanHome: File + get() = (PropertiesProvider(this).konanDataDir?.let { NativeCompilerDownloader(project).compilerDirectory } + ?: PropertiesProvider(this).nativeHome?.let { file(it) } + ?: NativeCompilerDownloader(project).compilerDirectory).absoluteFile internal val Project.disableKonanDaemon: Boolean get() = PropertiesProvider(this).nativeDisableCompilerDaemon == true @@ -47,6 +47,9 @@ internal val Project.konanVersion: String internal val Project.konanDataDir: String? get() = PropertiesProvider(this).konanDataDir +internal val Project.kotlinNativeToolchainEnabled: Boolean + get() = PropertiesProvider(this).kotlinNativeToolchainEnabled && PropertiesProvider(this).nativeDownloadFromMaven + internal fun Project.getKonanCacheKind(target: KonanTarget): NativeCacheKind { val commonCacheKind = PropertiesProvider(this).nativeCacheKind val targetCacheKind = PropertiesProvider(this).nativeCacheKindForTarget(target) @@ -71,9 +74,9 @@ internal fun Project.getKonanParallelThreads(): Int { private val Project.kotlinNativeCompilerJar: String get() = if (nativeUseEmbeddableCompilerJar) - "$konanHome/konan/lib/kotlin-native-compiler-embeddable.jar" + "${konanHome.absolutePath}/konan/lib/kotlin-native-compiler-embeddable.jar" else - "$konanHome/konan/lib/kotlin-native.jar" + "${konanHome.absolutePath}/konan/lib/kotlin-native.jar" internal abstract class KotlinNativeToolRunner( protected val toolName: String, @@ -271,7 +274,7 @@ internal class KotlinNativeLibraryGenerationRunner( companion object { @Suppress("DEPRECATION") // TODO(Dmitrii Krasnov): after KT-52567 it will be possible to use GradleExecutionContext#fromTaskContext here fun fromProject(project: Project) = KotlinNativeLibraryGenerationRunner( - settings = Settings.of(project.konanHome, project.konanDataDir, project), + settings = Settings.of(project.konanHome.absolutePath, project.konanDataDir, project), executionContext = GradleExecutionContext.fromProject(project), metricsReporter = GradleBuildMetricsReporter() ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/AbstractKotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/AbstractKotlinPlugin.kt index ec31c3a757b..7d1eab85086 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/AbstractKotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/AbstractKotlinPlugin.kt @@ -41,6 +41,7 @@ const val NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinNativeCom const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath" internal const val BUILD_TOOLS_API_CLASSPATH_CONFIGURATION_NAME = "kotlinBuildToolsApiClasspath" internal const val KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME = "kotlinKlibCommonizerClasspath" +internal const val KOTLIN_NATIVE_BUNDLE_CONFIGURATION_NAME = "kotlinNativeBundleConfiguration" private const val JAVA_TEST_FIXTURES_PLUGIN_ID = "java-test-fixtures" internal abstract class AbstractKotlinPlugin( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index abcaf91dee3..f54e9fafe53 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -23,6 +23,7 @@ import org.gradle.api.Project import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry +import org.jetbrains.kotlin.compilerRunner.kotlinNativeToolchainEnabled import org.jetbrains.kotlin.compilerRunner.maybeCreateCommonizerClasspathConfiguration import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.internal.KOTLIN_BUILD_TOOLS_API_IMPL @@ -43,6 +44,7 @@ import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnab import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerArtifactTypeAttribute import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropKlibLibraryElements import org.jetbrains.kotlin.gradle.targets.native.internal.CommonizerTargetAttribute +import org.jetbrains.kotlin.gradle.targets.native.toolchain.KotlinNativeBundleArtifactFormat import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry import org.jetbrains.kotlin.gradle.utils.* @@ -68,6 +70,9 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin { addKotlinCompilerConfiguration(project) + if (project.kotlinNativeToolchainEnabled) { + addKotlinNativeBundleConfiguration(project) + } project.configurations.maybeCreateResolvable(PLUGIN_CLASSPATH_CONFIGURATION_NAME).apply { isVisible = false @@ -115,6 +120,19 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin { } } + private fun addKotlinNativeBundleConfiguration(project: Project) { + project.configurations + .maybeCreateResolvable(KOTLIN_NATIVE_BUNDLE_CONFIGURATION_NAME).also { configuration -> + configuration.defaultDependencies { + it.add(project.dependencies.create(NativeCompilerDownloader.getCompilerDependencyNotation(project))) + } + configuration.attributes.setAttribute( + KotlinNativeBundleArtifactFormat.attribute, + KotlinNativeBundleArtifactFormat.KotlinNativeBundleArtifactsTypes.DIRECTORY + ) + } + } + private fun Project.registerDefaultVariantImplementations() { val factories = VariantImplementationFactoriesConfigurator.get(project.gradle) factories.putIfAbsent( @@ -206,6 +224,11 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin { CommonizerTargetAttribute.setupAttributesMatchingStrategy(this) CInteropCommonizerArtifactTypeAttribute.setupTransform(project) } + + if (project.kotlinNativeToolchainEnabled) { + KotlinNativeBundleArtifactFormat.setupAttributesMatchingStrategy(this) + KotlinNativeBundleArtifactFormat.setupTransform(project) + } } open fun whenBuildEvaluated(project: Project) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt index 371f504ecee..6c9b2edbdc2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt @@ -42,6 +42,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLI import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_IMPORT_ENABLE_SLOW_SOURCES_JAR_RESOLVER import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_IGNORE_DISABLED_TARGETS import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_SUPPRESS_EXPERIMENTAL_ARTIFACTS_DSL_WARNING +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_TOOLCHAIN_ENABLED import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_USE_XCODE_MESSAGE_STYLE import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_PUBLISH_JVM_ENVIRONMENT_ATTRIBUTE import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_RUN_COMPILER_VIA_BUILD_TOOLS_API @@ -501,6 +502,12 @@ internal class PropertiesProvider private constructor(private val project: Proje val appleCopyFrameworkToBuiltProductsDir: Boolean get() = booleanProperty(PropertyNames.KOTLIN_APPLE_COPY_FRAMEWORK_TO_BUILT_PRODUCTS_DIR) ?: true + /** + * Enables kotlin native toolchain in native projects. + */ + val kotlinNativeToolchainEnabled: Boolean + get() = booleanProperty(KOTLIN_NATIVE_TOOLCHAIN_ENABLED) ?: true + /** * Allows suppressing the diagnostic [KotlinToolingDiagnostics.BuildToolsApiVersionInconsistency]. * Required only for Kotlin repo bootstrapping. @@ -643,6 +650,7 @@ internal class PropertiesProvider private constructor(private val project: Proje val KOTLIN_USER_HOME_DIR = property("kotlin.user.home") val KOTLIN_PROJECT_PERSISTENT_DIR = property("kotlin.project.persistent.dir") val KOTLIN_PROJECT_PERSISTENT_DIR_GRADLE_DISABLE_WRITE = property("kotlin.project.persistent.dir.gradle.disableWrite") + val KOTLIN_NATIVE_TOOLCHAIN_ENABLED = property("kotlin.native.toolchain.enabled") val KOTLIN_APPLE_COPY_FRAMEWORK_TO_BUILT_PRODUCTS_DIR = property("kotlin.apple.copyFrameworkToBuiltProductsDir") /** diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KonanPropertiesBuildService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KonanPropertiesBuildService.kt index e35ae0915dc..95ad8f22f85 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KonanPropertiesBuildService.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KonanPropertiesBuildService.kt @@ -69,7 +69,7 @@ abstract class KonanPropertiesBuildService : BuildService = project.gradle.sharedServices.registerIfAbsent(serviceName, KonanPropertiesBuildService::class.java) { service -> - service.parameters.konanHome.set(project.rootProject.konanHome) + service.parameters.konanHome.set(project.rootProject.konanHome.absolutePath) }.also { serviceProvider -> SingleActionPerProject.run(project, UsesKonanPropertiesBuildService::class.java.name) { project.tasks.withType().configureEach { task -> diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt index 27129d52cd2..67a0febdeb7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt @@ -10,6 +10,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Project import org.jetbrains.kotlin.compilerRunner.konanHome +import org.jetbrains.kotlin.compilerRunner.kotlinNativeToolchainEnabled import org.jetbrains.kotlin.gradle.DeprecatedTargetPresetApi import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.targets.android.internal.InternalKotlinTargetPreset @@ -36,7 +37,7 @@ abstract class AbstractKotlinNativeTargetPreset( private fun setupNativeHomePrivateProperty() = with(project) { if (!hasProperty(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY)) - extensions.extraProperties.set(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY, konanHome) + extensions.extraProperties.set(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY, konanHome.absolutePath) } protected abstract fun createTargetConfigurator(): AbstractKotlinTargetConfigurator @@ -44,7 +45,9 @@ abstract class AbstractKotlinNativeTargetPreset( protected abstract fun instantiateTarget(name: String): T override fun createTargetInternal(name: String): T { - project.setupNativeCompiler(konanTarget) + if (!project.kotlinNativeToolchainEnabled) { + project.setupNativeCompiler(konanTarget) + } val result = instantiateTarget(name).apply { targetName = name diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt index d9726f167ae..7d6907ca94c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.plugin.internal.configurationTimePropertiesAccessor import org.jetbrains.kotlin.gradle.plugin.internal.usedAtConfigurationTime -import org.jetbrains.kotlin.gradle.targets.native.internal.NativeDistributionType import org.jetbrains.kotlin.gradle.targets.native.internal.NativeDistributionTypeProvider import org.jetbrains.kotlin.gradle.targets.native.internal.PlatformLibrariesGenerator import org.jetbrains.kotlin.konan.target.HostManager @@ -34,7 +33,6 @@ import java.nio.file.Files class NativeCompilerDownloader( val project: Project, - private val compilerVersion: String = project.konanVersion, ) { companion object { @@ -46,27 +44,36 @@ class NativeCompilerDownloader( internal const val BASE_DOWNLOAD_URL = "https://download.jetbrains.com/kotlin/native/builds" internal const val KOTLIN_GROUP_ID = "org.jetbrains.kotlin" - } - val compilerDirectory: File - get() = DependencyDirectories - .getLocalKonanDir(project.konanDataDir) - .resolve(dependencyNameWithOsAndVersion) + internal fun getCompilerDependencyNotation(project: Project): Map { + return mapOf( + "group" to KOTLIN_GROUP_ID, + "name" to getDependencyName(project), + "version" to getCompilerVersion(project), + "classifier" to simpleOsName, + "ext" to archiveExtension + ) + } - private val logger: Logger - get() = project.logger + internal fun getCompilerDirectory(project: Project): File { + return DependencyDirectories + .getLocalKonanDir(project.konanDataDir) + .resolve(getDependencyNameWithOsAndVersion(project)) + } - private val kotlinProperties get() = PropertiesProvider(project) + internal fun getDependencyNameWithOsAndVersion(project: Project): String { + return "${getDependencyName(project)}-$simpleOsName-${getCompilerVersion(project)}" + } - private val distributionType: NativeDistributionType - get() = NativeDistributionTypeProvider(project).getDistributionType() - private val simpleOsName: String - get() = HostManager.platformName() + private val simpleOsName = HostManager.platformName() - private val dependencyName: String - get() { - val dependencySuffix = distributionType.suffix + private fun getCompilerVersion(project: Project): String { + return project.konanVersion + } + + private fun getDependencyName(project: Project): String { + val dependencySuffix = NativeDistributionTypeProvider(project).getDistributionType().suffix return if (dependencySuffix != null) { "kotlin-native-$dependencySuffix" } else { @@ -74,22 +81,32 @@ class NativeCompilerDownloader( } } + private val archiveExtension + get() = if (useZip) { + "zip" + } else { + "tar.gz" + } + + private val useZip = HostManager.hostIsMingw + + } + + val compilerDirectory: File + get() = getCompilerDirectory(project) + + private val logger: Logger + get() = project.logger + + private val kotlinProperties get() = PropertiesProvider(project) + + private val dependencyNameWithOsAndVersion: String - get() = "$dependencyName-$simpleOsName-$compilerVersion" + get() = getDependencyNameWithOsAndVersion(project) private val dependencyFileName: String get() = "$dependencyNameWithOsAndVersion.$archiveExtension" - private val useZip - get() = HostManager.hostIsMingw - - private val archiveExtension - get() = if (useZip) { - "zip" - } else { - "tar.gz" - } - private fun archiveFileTree(archive: File): FileTree = if (useZip) { project.zipTree(archive) @@ -114,11 +131,11 @@ class NativeCompilerDownloader( } private val repoUrl by lazy { - val maturity = KotlinToolingVersion(compilerVersion).maturity + val maturity = KotlinToolingVersion(getCompilerVersion(project)).maturity buildString { append("${kotlinProperties.nativeBaseDownloadUrl}/") append(if (maturity == KotlinToolingVersion.Maturity.DEV) "dev/" else "releases/") - append("$compilerVersion/") + append("${getCompilerVersion(project)}/") append(simpleOsName) } } @@ -129,27 +146,19 @@ class NativeCompilerDownloader( } else null val compilerDependency = if (kotlinProperties.nativeDownloadFromMaven) { - project.dependencies.create( - mapOf( - "group" to KOTLIN_GROUP_ID, - "name" to dependencyName, - "version" to compilerVersion, - "classifier" to simpleOsName, - "ext" to archiveExtension - ) - ) + project.dependencies.create(getCompilerDependencyNotation(project)) } else { project.dependencies.create( mapOf( - "name" to "$dependencyName-$simpleOsName", - "version" to compilerVersion, + "name" to "${getDependencyName(project)}-$simpleOsName", + "version" to getCompilerVersion(project), "ext" to archiveExtension ) ) } val configuration = project.configurations.detachedResolvable(compilerDependency) - logger.lifecycle("\nPlease wait while Kotlin/Native compiler $compilerVersion is being installed.") + logger.lifecycle("\nPlease wait while Kotlin/Native compiler ${getCompilerVersion(project)} is being installed.") if (!kotlinProperties.nativeDownloadFromMaven) { val dependencyUrl = "$repoUrl/$dependencyFileName" @@ -162,6 +171,12 @@ class NativeCompilerDownloader( configuration.files.single() } + extractKotlinNativeFromArchive(archive) + + if (repo != null) removeRepo(repo) + } + + private fun extractKotlinNativeFromArchive(archive: File) { logger.kotlinInfo("Using Kotlin/Native compiler archive: ${archive.absolutePath}") logger.lifecycle("Unpack Kotlin/Native compiler to $compilerDirectory") @@ -186,8 +201,6 @@ class NativeCompilerDownloader( tmpDir.deleteRecursively() } } - - if (repo != null) removeRepo(repo) } fun downloadIfNeeded() { @@ -199,11 +212,12 @@ class NativeCompilerDownloader( private fun checkClassPath() { project.providers.of(NativeCompilerDownloaderClassPathChecker::class.java) { - it.parameters.classPath.setFrom(KotlinNativeToolRunner.Settings.of(project.konanHome, project.konanDataDir, project).classpath) + it.parameters.classPath.setFrom(KotlinNativeToolRunner.Settings.of(project.konanHome.absolutePath, project.konanDataDir, project).classpath) }.usedAtConfigurationTime(project.configurationTimePropertiesAccessor).get() } - internal abstract class NativeCompilerDownloaderClassPathChecker : ValueSource { + internal abstract class NativeCompilerDownloaderClassPathChecker : + ValueSource { interface Params : ValueSourceParameters { val classPath: ConfigurableFileCollection @@ -216,6 +230,19 @@ class NativeCompilerDownloader( } } +/** + * Sets up the Kotlin/Native compiler for the given project. + * + * @param konanTarget The target platform for the Kotlin/Native compiler. + */ +@Deprecated( + message = "This is old k/n downloading method that is used on configuration phase", + replaceWith = ReplaceWith( + "KotlinNativeInstaller", + "org.jetbrains.kotlin.gradle.targets.native.toolchain.KotlinNativeInstaller" + ), + level = DeprecationLevel.WARNING +) internal fun Project.setupNativeCompiler(konanTarget: KonanTarget) { val isKonanHomeOverridden = kotlinPropertiesProvider.nativeHome != null if (!isKonanHomeOverridden) { @@ -227,9 +254,9 @@ internal fun Project.setupNativeCompiler(konanTarget: KonanTarget) { } downloader.downloadIfNeeded() - logger.info("Kotlin/Native distribution: $konanHome") + logger.info("Kotlin/Native distribution: ${konanHome.absolutePath}") } else { - logger.info("User-provided Kotlin/Native distribution: $konanHome") + logger.info("User-provided Kotlin/Native distribution: ${konanHome.absolutePath}") } val distributionType = NativeDistributionTypeProvider(project).getDistributionType() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/PlatformLibrariesGenerator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/PlatformLibrariesGenerator.kt index 6406e493e32..4376e945ff0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/PlatformLibrariesGenerator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/PlatformLibrariesGenerator.kt @@ -29,7 +29,7 @@ import java.util.concurrent.ConcurrentHashMap internal class PlatformLibrariesGenerator(val project: Project, val konanTarget: KonanTarget) { private val distribution = - customerDistribution(project.konanHome, konanDataDir = project.konanDataDir) + customerDistribution(project.konanHome.absolutePath, konanDataDir = project.konanDataDir) private val platformLibsDirectory = File(distribution.platformLibs(konanTarget)).absoluteFile @@ -77,7 +77,7 @@ internal class PlatformLibrariesGenerator(val project: Project, val konanTarget: } val cacheDirectory = CacheBuilder.getRootCacheDirectory( - File(project.konanHome), konanTarget, true, konanCacheKind + project.konanHome, konanTarget, true, konanCacheKind ) return presentDefs.toPlatformLibNames().all { cacheDirectory.resolve(CacheBuilder.getCacheFileName(it, konanCacheKind)).listFilesOrEmpty().isNotEmpty() @@ -115,7 +115,7 @@ internal class PlatformLibrariesGenerator(val project: Project, val konanTarget: args.addArg("-cache-kind", konanCacheKind.produce!!) args.addArg( "-cache-directory", - CacheBuilder.getRootCacheDirectory(File(konanHome), konanTarget, true, konanCacheKind).absolutePath + CacheBuilder.getRootCacheDirectory(konanHome, konanTarget, true, konanCacheKind).absolutePath ) args.addArg("-cache-arg", "-g") val additionalCacheFlags = konanPropertiesService.additionalCacheFlags(konanTarget) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt index c9278b87cc8..045ebfd169c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeLink.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.targets.native.UsesKonanPropertiesBuildService import org.jetbrains.kotlin.gradle.targets.native.tasks.CompilerPluginData +import org.jetbrains.kotlin.gradle.targets.native.toolchain.KotlinNativeProvider import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.KonanTarget @@ -62,14 +63,6 @@ constructor( val compilation: KotlinNativeCompilation get() = binary.compilation - @get:Internal - val konanDataDir: Provider = project.provider { project.konanDataDir } - - @get:Internal - val konanHome: Provider = project.provider { project.konanHome } - - private val runnerSettings = KotlinNativeCompilerRunner.Settings.of(konanHome.get(), konanDataDir.getOrNull(), project) - final override val toolOptions: KotlinCommonCompilerToolOptions = objectFactory .newInstance() @@ -206,17 +199,29 @@ constructor( private val externalDependenciesArgs by lazy { ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() } private val cacheBuilderSettings by lazy { - CacheBuilder.Settings.createWithProject(konanHome.get(), konanDataDir.getOrNull(), project, binary, konanTarget, toolOptions, externalDependenciesArgs) + CacheBuilder.Settings.createWithProject( + kotlinNativeProvider.get().bundleDirectory.getFile().absolutePath, + kotlinNativeProvider.get().konanDataDir.orNull, + project, + binary, + konanTarget, + toolOptions, + externalDependenciesArgs + ) } - private class CacheSettings(val orchestration: NativeCacheOrchestration, val kind: NativeCacheKind, - val icEnabled: Boolean, val threads: Int, - val gradleUserHomeDir: File, val gradleBuildDir: File) + private class CacheSettings( + val orchestration: NativeCacheOrchestration, val kind: NativeCacheKind, + val icEnabled: Boolean, val threads: Int, + val gradleUserHomeDir: File, val gradleBuildDir: File, + ) private val cacheSettings by lazy { - CacheSettings(project.getKonanCacheOrchestration(), project.getKonanCacheKind(konanTarget), - project.isKonanIncrementalCompilationEnabled(), project.getKonanParallelThreads(), - project.gradle.gradleUserHomeDir, project.layout.buildDirectory.get().asFile) + CacheSettings( + project.getKonanCacheOrchestration(), project.getKonanCacheKind(konanTarget), + project.isKonanIncrementalCompilationEnabled(), project.getKonanParallelThreads(), + project.gradle.gradleUserHomeDir, project.layout.buildDirectory.get().asFile + ) } override fun createCompilerArguments(context: CreateCompilerArgumentsContext) = context.create { @@ -343,6 +348,31 @@ constructor( @get:Nested var kotlinPluginData: Provider? = null + @get:Nested + internal val kotlinNativeProvider: Provider = project.provider { + KotlinNativeProvider(project, konanTarget) + } + + @Deprecated( + message = "This property as a konanHome will be squashed into one in future releases.", + replaceWith = ReplaceWith("kotlinNativeProvider.konanDataDir") + ) + @get:Internal + val konanDataDir: Provider = kotlinNativeProvider.flatMap { it.konanDataDir } + + @Deprecated( + message = "This property as a konanDataDir will be squashed into one in future releases.", + replaceWith = ReplaceWith("kotlinNativeProvider.compilerDirectory") + ) + @get:Internal + val konanHome: Provider = kotlinNativeProvider.map { it.bundleDirectory.get().asFile.absolutePath } + + private val runnerSettings = KotlinNativeCompilerRunner.Settings.of( + kotlinNativeProvider.get().bundleDirectory.getFile().absolutePath, + kotlinNativeProvider.get().konanDataDir.orNull, + project + ) + @TaskAction fun compile() { val metricsReporter = metrics.get() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt index 58324981998..0a2c26798ac 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt @@ -39,9 +39,9 @@ import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.plugin.statistics.UsesBuildFusService import org.jetbrains.kotlin.gradle.report.* -import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.targets.native.KonanPropertiesBuildService import org.jetbrains.kotlin.gradle.targets.native.tasks.* +import org.jetbrains.kotlin.gradle.targets.native.toolchain.KotlinNativeProvider import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.gradle.utils.GradleLoggerAdapter import org.jetbrains.kotlin.gradle.utils.listFilesOrEmpty @@ -276,11 +276,6 @@ abstract class AbstractKotlinNativeCompile< } -// Remove it once actual K2NativeCompilerArguments will be available without 'kotlin.native.enabled = true' flag -class StubK2NativeCompilerArguments : CommonCompilerArguments() { - override fun copyOf(): Freezable = copyCommonCompilerArguments(this, StubK2NativeCompilerArguments()) -} - /** * A task producing a klibrary from a compilation. */ @@ -336,11 +331,24 @@ internal constructor( @get:Internal // these sources are normally a subset of `source` ones which are already tracked val commonSources: ConfigurableFileCollection = project.files() - @get:Internal - val konanDataDir: Provider = project.provider { project.konanDataDir } + @get:Nested + internal val kotlinNativeProvider: Provider = project.provider { + KotlinNativeProvider(project, konanTarget) + } + @Deprecated( + message = "This property as a konanHome will be squashed into one in future releases.", + replaceWith = ReplaceWith("kotlinNativeProvider.konanDataDir") + ) @get:Internal - val konanHome: Provider = project.provider { project.konanHome } + val konanDataDir: Provider = kotlinNativeProvider.flatMap { it.konanDataDir } + + @Deprecated( + message = "This property as a konanDataDir will be squashed into one in future releases.", + replaceWith = ReplaceWith("kotlinNativeProvider.compilerDirectory") + ) + @get:Internal + val konanHome: Provider = kotlinNativeProvider.map { it.bundleDirectory.get().asFile.absolutePath } @get:Nested override val multiplatformStructure: K2MultiplatformStructure = objectFactory.newInstance() @@ -410,7 +418,11 @@ internal constructor( override val additionalCompilerOptions: Provider> get() = compilerOptions.freeCompilerArgs as Provider> - private val runnerSettings = KotlinNativeCompilerRunner.Settings.of(konanHome.get(), konanDataDir.getOrNull(), project) + private val runnerSettings = KotlinNativeCompilerRunner.Settings.of( + kotlinNativeProvider.get().bundleDirectory.getFile().absolutePath, + kotlinNativeProvider.get().konanDataDir.orNull, + project + ) // endregion. @Suppress("DeprecatedCallableAddReplaceWith") @@ -1077,13 +1089,30 @@ abstract class CInteropProcess @Inject internal constructor(params: Params) : val outputFile: File get() = outputFileProvider.get() - @get:Internal - val konanDataDir: Provider = project.provider { project.konanDataDir } + @get:Nested + internal val kotlinNativeProvider: Provider = project.provider { + KotlinNativeProvider(project, konanTarget) + } + @Deprecated( + message = "This property as a konanHome will be squashed into one in future releases.", + replaceWith = ReplaceWith("kotlinNativeProvider.konanDataDir") + ) @get:Internal - val konanHome: Provider = project.provider { project.konanHome } + val konanDataDir: Provider = kotlinNativeProvider.flatMap { it.konanDataDir } - private val runnerSettings = KotlinNativeToolRunner.Settings.of(konanHome.get(), konanDataDir.getOrNull(), project) + @Deprecated( + message = "This property as a konanDataDir will be squashed into one in future releases.", + replaceWith = ReplaceWith("kotlinNativeProvider.compilerDirectory") + ) + @get:Internal + val konanHome: Provider = kotlinNativeProvider.map { it.bundleDirectory.get().asFile.absolutePath } + + private val runnerSettings = KotlinNativeToolRunner.Settings.of( + kotlinNativeProvider.get().bundleDirectory.getFile().absolutePath, + kotlinNativeProvider.get().konanDataDir.orNull, + project + ) // Inputs and outputs. @OutputFile diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt index be44d667777..d17b428e1dd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/artifact/KotlinNativeLinkArtifactTask.kt @@ -23,10 +23,8 @@ import org.gradle.work.DisableCachingByDefault import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime +import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.compilerRunner.KotlinNativeCompilerRunner -import org.jetbrains.kotlin.compilerRunner.KotlinToolRunner -import org.jetbrains.kotlin.compilerRunner.konanDataDir -import org.jetbrains.kotlin.compilerRunner.konanHome import org.jetbrains.kotlin.compilerRunner.addBuildMetricsForTaskAction import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated @@ -35,8 +33,10 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.BitcodeEmbeddingMode import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.targets.native.tasks.buildKotlinNativeBinaryLinkerArgs +import org.jetbrains.kotlin.gradle.targets.native.toolchain.KotlinNativeProvider import org.jetbrains.kotlin.gradle.tasks.KotlinToolTask import org.jetbrains.kotlin.gradle.utils.XcodeUtils +import org.jetbrains.kotlin.gradle.utils.getFile import org.jetbrains.kotlin.gradle.utils.newInstance import org.jetbrains.kotlin.gradle.utils.property import org.jetbrains.kotlin.konan.target.CompilerOutputKind @@ -170,13 +170,30 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor( val metrics: Property> = project.objects .property(GradleBuildMetricsReporter()) - @get:Internal - val konanDataDir: Provider = project.provider { project.konanDataDir } + @get:Nested + internal val kotlinNativeProvider: Provider = project.provider { + KotlinNativeProvider(project, konanTarget) + } + @Deprecated( + message = "This property as a konanHome will be squashed into one in future releases.", + replaceWith = ReplaceWith("kotlinNativeProvider.konanDataDir") + ) @get:Internal - val konanHome: Provider = project.provider { project.konanHome } + val konanDataDir: Provider = kotlinNativeProvider.flatMap { it.konanDataDir } - private val runnerSettings = KotlinNativeCompilerRunner.Settings.of(konanHome.get(), konanDataDir.getOrNull(), project) + @Deprecated( + message = "This property as a konanDataDir will be squashed into one in future releases.", + replaceWith = ReplaceWith("kotlinNativeProvider.compilerDirectory") + ) + @get:Internal + val konanHome: Provider = kotlinNativeProvider.map { it.bundleDirectory.get().asFile.absolutePath } + + private val runnerSettings = KotlinNativeCompilerRunner.Settings.of( + kotlinNativeProvider.get().bundleDirectory.getFile().absolutePath, + kotlinNativeProvider.get().konanDataDir.orNull, + project + ) init { baseName.convention(project.name) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/KotlinNativeBundleArtifactFormat.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/KotlinNativeBundleArtifactFormat.kt new file mode 100644 index 00000000000..fbb08f13d44 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/KotlinNativeBundleArtifactFormat.kt @@ -0,0 +1,57 @@ +/* + * 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.targets.native.toolchain + +import org.gradle.api.Project +import org.gradle.api.attributes.Attribute +import org.gradle.api.attributes.AttributesSchema +import org.jetbrains.kotlin.gradle.utils.setAttribute + +/** + * This class provides functionality for setting up attributes matching strategy and + * transformation for a Kotlin Native Bundle configurations. + * + * @property attribute The attribute object representing the Kotlin Native Bundle type. + */ +internal object KotlinNativeBundleArtifactFormat { + + val attribute: Attribute = + Attribute.of("kotlin.native.bundle.type", KotlinNativeBundleArtifactsTypes::class.java) + + internal enum class KotlinNativeBundleArtifactsTypes { + ARCHIVE, + DIRECTORY + } + + /** + * Sets up the attributes matching strategy for the given attributes schema. + * + * @param attributesSchema The attributes schema to set up the matching strategy for. + */ + internal fun setupAttributesMatchingStrategy(attributesSchema: AttributesSchema) { + attributesSchema.attribute(attribute) + } + + /** + * Sets up the necessary transformations for handling artifact types "tar.gz" and "zip" in the given project. + * + * @param project The project in which to set up the transformations. + */ + internal fun setupTransform(project: Project) { + project.dependencies.artifactTypes.maybeCreate("tar.gz").also { artifactType -> + artifactType.attributes.setAttribute(attribute, KotlinNativeBundleArtifactsTypes.ARCHIVE) + } + + project.dependencies.artifactTypes.maybeCreate("zip").also { artifactType -> + artifactType.attributes.setAttribute(attribute, KotlinNativeBundleArtifactsTypes.ARCHIVE) + } + + project.dependencies.registerTransform(UnzipTransformationAction::class.java) { transform -> + transform.from.setAttribute(attribute, KotlinNativeBundleArtifactsTypes.ARCHIVE) + transform.to.setAttribute(attribute, KotlinNativeBundleArtifactsTypes.DIRECTORY) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/KotlinNativeProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/KotlinNativeProvider.kt new file mode 100644 index 00000000000..df0d4e43918 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/KotlinNativeProvider.kt @@ -0,0 +1,110 @@ +/* + * 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.targets.native.toolchain + +import org.gradle.api.Project +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.jetbrains.kotlin.compilerRunner.konanDataDir +import org.jetbrains.kotlin.compilerRunner.konanHome +import org.jetbrains.kotlin.compilerRunner.kotlinNativeToolchainEnabled +import org.jetbrains.kotlin.gradle.plugin.KOTLIN_NATIVE_BUNDLE_CONFIGURATION_NAME +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider +import org.jetbrains.kotlin.gradle.targets.native.internal.NativeDistributionTypeProvider +import org.jetbrains.kotlin.gradle.targets.native.internal.PlatformLibrariesGenerator +import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader +import org.jetbrains.kotlin.gradle.utils.filesProvider +import org.jetbrains.kotlin.gradle.utils.property +import org.jetbrains.kotlin.konan.target.KonanTarget +import java.io.File + +/** + * This is a nested provider for all native tasks + */ +internal class KotlinNativeProvider(project: Project, konanTarget: KonanTarget) { + + @get:Internal + val konanDataDir: Provider = project.provider { project.konanDataDir } + + @get:Internal + val bundleDirectory: DirectoryProperty = project.objects.directoryProperty().fileProvider( + project.provider { + project.konanHome + } + ) + + @get:Internal + val reinstallBundle: Property = project.objects.property(project.kotlinPropertiesProvider.nativeReinstall) + + @get:Input + internal val kotlinNativeBundleVersion: Provider = bundleDirectory.zip(reinstallBundle) { bundleDir, reinstallFlag -> + val kotlinNativeVersion = NativeCompilerDownloader.getDependencyNameWithOsAndVersion(project) + if (project.kotlinNativeToolchainEnabled && (reinstallFlag || !bundleDir.asFile.exists())) { + val kotlinNativeCompilerExtractedFolder = + kotlinNativeCompilerConfiguration + .singleOrNull() + ?.resolve(kotlinNativeVersion) + ?: error( + "Kotlin Native dependency has not been properly resolved. " + + "Please, make sure that you've declared the repository, which contains $kotlinNativeVersion." + ) + + project.prepareKotlinNativeBundle( + bundleDir.asFile, + reinstallFlag, + kotlinNativeCompilerExtractedFolder, + konanTarget + ) + } + kotlinNativeVersion + } + + private val kotlinNativeCompilerConfiguration: ConfigurableFileCollection = project.filesProvider { + // without enabled there is no configuration with this name, so we should return empty provider to support configuraiton cache + if (project.kotlinNativeToolchainEnabled) { + project.configurations.named( + KOTLIN_NATIVE_BUNDLE_CONFIGURATION_NAME + ) + } else { + null + } + } + + private fun Project.prepareKotlinNativeBundle( + bundleDir: File, + reinstallFlag: Boolean, + gradleCachesKotlinNativeDir: File, + konanTarget: KonanTarget, + ) { + + if (reinstallFlag) { + NativeCompilerDownloader.getCompilerDirectory(project).deleteRecursively() + } + + if (!bundleDir.exists()) { + logger.info("Moving Kotlin/Native bundle from tmp directory $gradleCachesKotlinNativeDir to ${bundleDir.absolutePath}") + copy { + it.from(gradleCachesKotlinNativeDir) + it.into(bundleDir) + } + logger.info("Moved Kotlin/Native bundle from $gradleCachesKotlinNativeDir to ${bundleDir.absolutePath}") + } + + setupKotlinNativeDependencies(konanTarget) + } + + private fun Project.setupKotlinNativeDependencies(konanTarget: KonanTarget) { + val distributionType = NativeDistributionTypeProvider(this).getDistributionType() + if (distributionType.mustGeneratePlatformLibs) { + PlatformLibrariesGenerator(project, konanTarget).generatePlatformLibsIfNeeded() + } + } + +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/UnzipTransformationAction.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/UnzipTransformationAction.kt new file mode 100644 index 00000000000..2171e33c02c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/toolchain/UnzipTransformationAction.kt @@ -0,0 +1,59 @@ +/* + * 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.targets.native.toolchain + +import org.gradle.api.artifacts.transform.InputArtifact +import org.gradle.api.artifacts.transform.TransformAction +import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.transform.TransformParameters +import org.gradle.api.file.ArchiveOperations +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.file.FileSystemOperations +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.work.DisableCachingByDefault +import java.io.File +import javax.inject.Inject + + +private const val EXTRACTED_ARCHIVE_RELATED_PATH = "extracted" + +/** + * An implementation of a gradle [TransformAction] to unzip configurations' artifacts in `tar.gz` and `zip` formats. + */ +@DisableCachingByDefault(because = "Does only I/O") +abstract class UnzipTransformationAction : TransformAction { + + @get:Inject + abstract val archiveOperations: ArchiveOperations + + @get:Inject + abstract val fileSystemOperations: FileSystemOperations + + @get:InputArtifact + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val inputArtifact: Provider + + override fun transform(outputs: TransformOutputs) { + val input = inputArtifact.get().asFile + val unzipDir = outputs.dir(EXTRACTED_ARCHIVE_RELATED_PATH) + unzipTo(input, unzipDir) + } + + private fun unzipTo(archive: File, outputDir: File) { + fileSystemOperations.copy { + it.from( + when { + archive.name.endsWith("zip") -> archiveOperations.zipTree(archive) + archive.name.endsWith(".tar.gz") -> archiveOperations.tarTree(archive) + else -> error("Unsupported format for unzipping $archive") + } + ) + it.into(outputDir) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinNativeToolchainTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinNativeToolchainTest.kt new file mode 100644 index 00000000000..cdd8a6075d9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinNativeToolchainTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2024 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.unitTests + +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.extraProperties +import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile +import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP +import org.jetbrains.kotlin.konan.target.HostManager +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals + +private const val STABLE_VERSION = "1.9.20" + +@Ignore(value = "We need to provide proper way of validating k/n dependencies: KT-52483") +class KotlinNativeToolchainTest { + + @Test + fun `check that kotlin native compiler stable version has been resolved correctly`() { + val project = buildProjectWithMPP { + project.multiplatformExtension.linuxX64() + project.extraProperties.set("kotlin.native.version", STABLE_VERSION) + project.extraProperties.set("kotlin.native.distribution.downloadFromMaven", true) + } + + project.evaluate() + + val compileTask = project.tasks.withType(KotlinNativeCompile::class.java).first() + + assertEquals( + "kotlin-native-prebuilt-${HostManager.platformName()}-$STABLE_VERSION", + compileTask.kotlinNativeProvider.get().kotlinNativeBundleVersion.get() + ) + } +} \ No newline at end of file diff --git a/native/commonizer-api/test/org/jetbrains/kotlin/commonizer/utils/konanHome.kt b/native/commonizer-api/test/org/jetbrains/kotlin/commonizer/utils/konanHome.kt index c2268f6dcfd..26e26b88c1f 100644 --- a/native/commonizer-api/test/org/jetbrains/kotlin/commonizer/utils/konanHome.kt +++ b/native/commonizer-api/test/org/jetbrains/kotlin/commonizer/utils/konanHome.kt @@ -20,9 +20,6 @@ internal val konanHome: File by lazy { .run { project.plugins.apply("kotlin-multiplatform") - // TODO(Dmitrii Krasnov): remove this, when KT-58303 is done - project.extraProperties.set("kotlin.native.distribution.downloadFromMaven","false") - (project.kotlinExtension as KotlinMultiplatformExtension).apply { macosX64() macosArm64()