[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
This commit is contained in:
committed by
Space Team
parent
48f5e1d05c
commit
7165d15d59
+32
@@ -20,7 +20,12 @@ import org.gradle.api.logging.LogLevel
|
|||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildReportType
|
import org.jetbrains.kotlin.gradle.report.BuildReportType
|
||||||
import org.jetbrains.kotlin.gradle.testbase.*
|
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.DisplayName
|
||||||
|
import org.junit.jupiter.api.io.TempDir
|
||||||
|
import java.nio.file.Path
|
||||||
import kotlin.io.path.ExperimentalPathApi
|
import kotlin.io.path.ExperimentalPathApi
|
||||||
import kotlin.io.path.readText
|
import kotlin.io.path.readText
|
||||||
import kotlin.io.path.relativeTo
|
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
|
//doesn't work for build history files approach
|
||||||
@DisplayName("Restore from build cache should not break incremental compilation")
|
@DisplayName("Restore from build cache should not break incremental compilation")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
|
|||||||
+15
-3
@@ -20,8 +20,13 @@ import org.gradle.api.logging.LogLevel
|
|||||||
import org.gradle.testkit.runner.BuildResult
|
import org.gradle.testkit.runner.BuildResult
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.testbase.*
|
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.DisplayName
|
||||||
|
import org.junit.jupiter.api.io.TempDir
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.nio.file.Path
|
||||||
import kotlin.io.path.*
|
import kotlin.io.path.*
|
||||||
|
|
||||||
@DisplayName("Build cache relocation")
|
@DisplayName("Build cache relocation")
|
||||||
@@ -204,9 +209,16 @@ class BuildCacheRelocationIT : KGPBaseTest() {
|
|||||||
@DisplayName("with native project")
|
@DisplayName("with native project")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testRelocationNative(gradleVersion: GradleVersion) {
|
fun testRelocationNative(gradleVersion: GradleVersion) {
|
||||||
|
val buildOptionsBeforeCaching = defaultBuildOptions.copy(
|
||||||
|
nativeOptions = super.defaultBuildOptions.nativeOptions.copy(
|
||||||
|
version = TestVersions.Kotlin.STABLE_RELEASE,
|
||||||
|
distributionDownloadFromMaven = true
|
||||||
|
)
|
||||||
|
)
|
||||||
val (firstProject, secondProject) = prepareTestProjects(
|
val (firstProject, secondProject) = prepareTestProjects(
|
||||||
"native-build-cache",
|
"native-build-cache",
|
||||||
gradleVersion
|
gradleVersion,
|
||||||
|
buildOptions = buildOptionsBeforeCaching
|
||||||
) {
|
) {
|
||||||
val localRepoUri = it.projectPath.resolve("repo").toUri()
|
val localRepoUri = it.projectPath.resolve("repo").toUri()
|
||||||
it.subProject("build-cache-app").buildGradleKts.append(
|
it.subProject("build-cache-app").buildGradleKts.append(
|
||||||
@@ -276,12 +288,12 @@ class BuildCacheRelocationIT : KGPBaseTest() {
|
|||||||
buildJdk: File? = null,
|
buildJdk: File? = null,
|
||||||
additionalConfiguration: (TestProject) -> Unit = {}
|
additionalConfiguration: (TestProject) -> Unit = {}
|
||||||
): Pair<TestProject, TestProject> {
|
): Pair<TestProject, TestProject> {
|
||||||
val firstProject = project(projectName, gradleVersion, buildOptions, buildJdk = buildJdk) {
|
val firstProject = project(projectName, gradleVersion, buildOptions, buildJdk = buildJdk, forceOutput = true) {
|
||||||
enableLocalBuildCache(localBuildCacheDir)
|
enableLocalBuildCache(localBuildCacheDir)
|
||||||
additionalConfiguration(this)
|
additionalConfiguration(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
val secondProject = project(projectName, gradleVersion, buildOptions, buildJdk = buildJdk) {
|
val secondProject = project(projectName, gradleVersion, buildOptions, buildJdk = buildJdk, forceOutput = true) {
|
||||||
enableLocalBuildCache(localBuildCacheDir)
|
enableLocalBuildCache(localBuildCacheDir)
|
||||||
additionalConfiguration(this)
|
additionalConfiguration(this)
|
||||||
}
|
}
|
||||||
|
|||||||
+144
@@ -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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -27,6 +27,15 @@ import kotlin.io.path.appendText
|
|||||||
)
|
)
|
||||||
@DisplayName("Tests for K/N builds with native downloading and platform libs")
|
@DisplayName("Tests for K/N builds with native downloading and platform libs")
|
||||||
@NativeGradlePluginTests
|
@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() {
|
class NativeDownloadAndPlatformLibsIT : KGPBaseTest() {
|
||||||
|
|
||||||
private val platformName: String = HostManager.platformName()
|
private val platformName: String = HostManager.platformName()
|
||||||
@@ -34,6 +43,8 @@ class NativeDownloadAndPlatformLibsIT : KGPBaseTest() {
|
|||||||
|
|
||||||
override val defaultBuildOptions: BuildOptions
|
override val defaultBuildOptions: BuildOptions
|
||||||
get() = super.defaultBuildOptions.withBundledKotlinNative().copy(
|
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,
|
// For each test in this class, we need to provide an isolated .konan directory,
|
||||||
// so we create it within each test project folder
|
// so we create it within each test project folder
|
||||||
konanDataDir = workingDir.resolve(".konan")
|
konanDataDir = workingDir.resolve(".konan")
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ interface TestVersions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Kotlin {
|
object Kotlin {
|
||||||
const val STABLE_RELEASE = "1.9.20"
|
const val STABLE_RELEASE = "1.9.21"
|
||||||
|
|
||||||
// Copied from KOTLIN_VERSION.kt file
|
// Copied from KOTLIN_VERSION.kt file
|
||||||
val CURRENT
|
val CURRENT
|
||||||
|
|||||||
+14
-11
@@ -62,17 +62,20 @@ fun getOutputForTask(taskPath: String, output: String, logLevel: LogLevel = LogL
|
|||||||
LogLevel.DEBUG -> taskOutputRegexForDebugLog(taskPath)
|
LogLevel.DEBUG -> taskOutputRegexForDebugLog(taskPath)
|
||||||
else -> throw throw IllegalStateException("Unsupported log lever for task output was given: $logLevel")
|
else -> throw throw IllegalStateException("Unsupported log lever for task output was given: $logLevel")
|
||||||
})
|
})
|
||||||
.find(output)
|
.findAll(output)
|
||||||
?.let { it.groupValues[1] }
|
.map { it.groupValues[1] }
|
||||||
?: error(
|
.joinToString(System.lineSeparator())
|
||||||
"""
|
.ifEmpty {
|
||||||
Could not find output for task $taskPath.
|
error(
|
||||||
=================
|
"""
|
||||||
Build output is:
|
Could not find output for task $taskPath.
|
||||||
$output
|
=================
|
||||||
=================
|
Build output is:
|
||||||
""".trimIndent()
|
$output
|
||||||
)
|
=================
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
class CommandLineArguments(
|
class CommandLineArguments(
|
||||||
val args: List<String>,
|
val args: List<String>,
|
||||||
|
|||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform") apply false
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
<SingleNativeTarget>()
|
||||||
|
}
|
||||||
+8
@@ -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")
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
<SingleNativeTarget>()
|
||||||
|
}
|
||||||
+8
@@ -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")
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
rootProject.name = "native-multi-module-project"
|
||||||
|
include("native1")
|
||||||
|
include("native2")
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
<SingleNativeTarget>()
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun main() {
|
||||||
|
println("Hello from simple native project")
|
||||||
|
}
|
||||||
+10
-7
@@ -32,10 +32,10 @@ import java.util.*
|
|||||||
private val Project.jvmArgs
|
private val Project.jvmArgs
|
||||||
get() = PropertiesProvider(this).nativeJvmArgs?.split("\\s+".toRegex()).orEmpty()
|
get() = PropertiesProvider(this).nativeJvmArgs?.split("\\s+".toRegex()).orEmpty()
|
||||||
|
|
||||||
internal val Project.konanHome: String
|
internal val Project.konanHome: File
|
||||||
get() = PropertiesProvider(this).konanDataDir?.let { NativeCompilerDownloader(project).compilerDirectory.absolutePath }
|
get() = (PropertiesProvider(this).konanDataDir?.let { NativeCompilerDownloader(project).compilerDirectory }
|
||||||
?: PropertiesProvider(this).nativeHome?.let { file(it).absolutePath }
|
?: PropertiesProvider(this).nativeHome?.let { file(it) }
|
||||||
?: NativeCompilerDownloader(project).compilerDirectory.absolutePath
|
?: NativeCompilerDownloader(project).compilerDirectory).absoluteFile
|
||||||
|
|
||||||
internal val Project.disableKonanDaemon: Boolean
|
internal val Project.disableKonanDaemon: Boolean
|
||||||
get() = PropertiesProvider(this).nativeDisableCompilerDaemon == true
|
get() = PropertiesProvider(this).nativeDisableCompilerDaemon == true
|
||||||
@@ -47,6 +47,9 @@ internal val Project.konanVersion: String
|
|||||||
internal val Project.konanDataDir: String?
|
internal val Project.konanDataDir: String?
|
||||||
get() = PropertiesProvider(this).konanDataDir
|
get() = PropertiesProvider(this).konanDataDir
|
||||||
|
|
||||||
|
internal val Project.kotlinNativeToolchainEnabled: Boolean
|
||||||
|
get() = PropertiesProvider(this).kotlinNativeToolchainEnabled && PropertiesProvider(this).nativeDownloadFromMaven
|
||||||
|
|
||||||
internal fun Project.getKonanCacheKind(target: KonanTarget): NativeCacheKind {
|
internal fun Project.getKonanCacheKind(target: KonanTarget): NativeCacheKind {
|
||||||
val commonCacheKind = PropertiesProvider(this).nativeCacheKind
|
val commonCacheKind = PropertiesProvider(this).nativeCacheKind
|
||||||
val targetCacheKind = PropertiesProvider(this).nativeCacheKindForTarget(target)
|
val targetCacheKind = PropertiesProvider(this).nativeCacheKindForTarget(target)
|
||||||
@@ -71,9 +74,9 @@ internal fun Project.getKonanParallelThreads(): Int {
|
|||||||
|
|
||||||
private val Project.kotlinNativeCompilerJar: String
|
private val Project.kotlinNativeCompilerJar: String
|
||||||
get() = if (nativeUseEmbeddableCompilerJar)
|
get() = if (nativeUseEmbeddableCompilerJar)
|
||||||
"$konanHome/konan/lib/kotlin-native-compiler-embeddable.jar"
|
"${konanHome.absolutePath}/konan/lib/kotlin-native-compiler-embeddable.jar"
|
||||||
else
|
else
|
||||||
"$konanHome/konan/lib/kotlin-native.jar"
|
"${konanHome.absolutePath}/konan/lib/kotlin-native.jar"
|
||||||
|
|
||||||
internal abstract class KotlinNativeToolRunner(
|
internal abstract class KotlinNativeToolRunner(
|
||||||
protected val toolName: String,
|
protected val toolName: String,
|
||||||
@@ -271,7 +274,7 @@ internal class KotlinNativeLibraryGenerationRunner(
|
|||||||
companion object {
|
companion object {
|
||||||
@Suppress("DEPRECATION") // TODO(Dmitrii Krasnov): after KT-52567 it will be possible to use GradleExecutionContext#fromTaskContext here
|
@Suppress("DEPRECATION") // TODO(Dmitrii Krasnov): after KT-52567 it will be possible to use GradleExecutionContext#fromTaskContext here
|
||||||
fun fromProject(project: Project) = KotlinNativeLibraryGenerationRunner(
|
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),
|
executionContext = GradleExecutionContext.fromProject(project),
|
||||||
metricsReporter = GradleBuildMetricsReporter()
|
metricsReporter = GradleBuildMetricsReporter()
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -41,6 +41,7 @@ const val NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinNativeCom
|
|||||||
const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath"
|
const val COMPILER_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerClasspath"
|
||||||
internal const val BUILD_TOOLS_API_CLASSPATH_CONFIGURATION_NAME = "kotlinBuildToolsApiClasspath"
|
internal const val BUILD_TOOLS_API_CLASSPATH_CONFIGURATION_NAME = "kotlinBuildToolsApiClasspath"
|
||||||
internal const val KLIB_COMMONIZER_CLASSPATH_CONFIGURATION_NAME = "kotlinKlibCommonizerClasspath"
|
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"
|
private const val JAVA_TEST_FIXTURES_PLUGIN_ID = "java-test-fixtures"
|
||||||
|
|
||||||
internal abstract class AbstractKotlinPlugin(
|
internal abstract class AbstractKotlinPlugin(
|
||||||
|
|||||||
+23
@@ -23,6 +23,7 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.kotlinNativeToolchainEnabled
|
||||||
import org.jetbrains.kotlin.compilerRunner.maybeCreateCommonizerClasspathConfiguration
|
import org.jetbrains.kotlin.compilerRunner.maybeCreateCommonizerClasspathConfiguration
|
||||||
import org.jetbrains.kotlin.gradle.dsl.*
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.internal.KOTLIN_BUILD_TOOLS_API_IMPL
|
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.CInteropCommonizerArtifactTypeAttribute
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropKlibLibraryElements
|
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.internal.CommonizerTargetAttribute
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.native.toolchain.KotlinNativeBundleArtifactFormat
|
||||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool
|
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool
|
||||||
import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry
|
import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry
|
||||||
import org.jetbrains.kotlin.gradle.utils.*
|
import org.jetbrains.kotlin.gradle.utils.*
|
||||||
@@ -68,6 +70,9 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin {
|
|||||||
|
|
||||||
addKotlinCompilerConfiguration(project)
|
addKotlinCompilerConfiguration(project)
|
||||||
|
|
||||||
|
if (project.kotlinNativeToolchainEnabled) {
|
||||||
|
addKotlinNativeBundleConfiguration(project)
|
||||||
|
}
|
||||||
|
|
||||||
project.configurations.maybeCreateResolvable(PLUGIN_CLASSPATH_CONFIGURATION_NAME).apply {
|
project.configurations.maybeCreateResolvable(PLUGIN_CLASSPATH_CONFIGURATION_NAME).apply {
|
||||||
isVisible = false
|
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() {
|
private fun Project.registerDefaultVariantImplementations() {
|
||||||
val factories = VariantImplementationFactoriesConfigurator.get(project.gradle)
|
val factories = VariantImplementationFactoriesConfigurator.get(project.gradle)
|
||||||
factories.putIfAbsent(
|
factories.putIfAbsent(
|
||||||
@@ -206,6 +224,11 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin {
|
|||||||
CommonizerTargetAttribute.setupAttributesMatchingStrategy(this)
|
CommonizerTargetAttribute.setupAttributesMatchingStrategy(this)
|
||||||
CInteropCommonizerArtifactTypeAttribute.setupTransform(project)
|
CInteropCommonizerArtifactTypeAttribute.setupTransform(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (project.kotlinNativeToolchainEnabled) {
|
||||||
|
KotlinNativeBundleArtifactFormat.setupAttributesMatchingStrategy(this)
|
||||||
|
KotlinNativeBundleArtifactFormat.setupTransform(project)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun whenBuildEvaluated(project: Project) {
|
open fun whenBuildEvaluated(project: Project) {
|
||||||
|
|||||||
+8
@@ -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_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_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_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_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_PUBLISH_JVM_ENVIRONMENT_ATTRIBUTE
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_RUN_COMPILER_VIA_BUILD_TOOLS_API
|
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
|
val appleCopyFrameworkToBuiltProductsDir: Boolean
|
||||||
get() = booleanProperty(PropertyNames.KOTLIN_APPLE_COPY_FRAMEWORK_TO_BUILT_PRODUCTS_DIR) ?: true
|
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].
|
* Allows suppressing the diagnostic [KotlinToolingDiagnostics.BuildToolsApiVersionInconsistency].
|
||||||
* Required only for Kotlin repo bootstrapping.
|
* 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_USER_HOME_DIR = property("kotlin.user.home")
|
||||||
val KOTLIN_PROJECT_PERSISTENT_DIR = property("kotlin.project.persistent.dir")
|
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_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")
|
val KOTLIN_APPLE_COPY_FRAMEWORK_TO_BUILT_PRODUCTS_DIR = property("kotlin.apple.copyFrameworkToBuiltProductsDir")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -69,7 +69,7 @@ abstract class KonanPropertiesBuildService : BuildService<KonanPropertiesBuildSe
|
|||||||
companion object {
|
companion object {
|
||||||
fun registerIfAbsent(project: Project): Provider<KonanPropertiesBuildService> =
|
fun registerIfAbsent(project: Project): Provider<KonanPropertiesBuildService> =
|
||||||
project.gradle.sharedServices.registerIfAbsent(serviceName, KonanPropertiesBuildService::class.java) { service ->
|
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 ->
|
}.also { serviceProvider ->
|
||||||
SingleActionPerProject.run(project, UsesKonanPropertiesBuildService::class.java.name) {
|
SingleActionPerProject.run(project, UsesKonanPropertiesBuildService::class.java.name) {
|
||||||
project.tasks.withType<UsesKonanPropertiesBuildService>().configureEach { task ->
|
project.tasks.withType<UsesKonanPropertiesBuildService>().configureEach { task ->
|
||||||
|
|||||||
+5
-2
@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.compilerRunner.konanHome
|
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.kotlinNativeToolchainEnabled
|
||||||
import org.jetbrains.kotlin.gradle.DeprecatedTargetPresetApi
|
import org.jetbrains.kotlin.gradle.DeprecatedTargetPresetApi
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.android.internal.InternalKotlinTargetPreset
|
import org.jetbrains.kotlin.gradle.targets.android.internal.InternalKotlinTargetPreset
|
||||||
@@ -36,7 +37,7 @@ abstract class AbstractKotlinNativeTargetPreset<T : KotlinNativeTarget>(
|
|||||||
|
|
||||||
private fun setupNativeHomePrivateProperty() = with(project) {
|
private fun setupNativeHomePrivateProperty() = with(project) {
|
||||||
if (!hasProperty(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY))
|
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<T>
|
protected abstract fun createTargetConfigurator(): AbstractKotlinTargetConfigurator<T>
|
||||||
@@ -44,7 +45,9 @@ abstract class AbstractKotlinNativeTargetPreset<T : KotlinNativeTarget>(
|
|||||||
protected abstract fun instantiateTarget(name: String): T
|
protected abstract fun instantiateTarget(name: String): T
|
||||||
|
|
||||||
override fun createTargetInternal(name: String): T {
|
override fun createTargetInternal(name: String): T {
|
||||||
project.setupNativeCompiler(konanTarget)
|
if (!project.kotlinNativeToolchainEnabled) {
|
||||||
|
project.setupNativeCompiler(konanTarget)
|
||||||
|
}
|
||||||
|
|
||||||
val result = instantiateTarget(name).apply {
|
val result = instantiateTarget(name).apply {
|
||||||
targetName = name
|
targetName = name
|
||||||
|
|||||||
+75
-48
@@ -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.PropertiesProvider.Companion.kotlinPropertiesProvider
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.configurationTimePropertiesAccessor
|
import org.jetbrains.kotlin.gradle.plugin.internal.configurationTimePropertiesAccessor
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.usedAtConfigurationTime
|
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.NativeDistributionTypeProvider
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.PlatformLibrariesGenerator
|
import org.jetbrains.kotlin.gradle.targets.native.internal.PlatformLibrariesGenerator
|
||||||
import org.jetbrains.kotlin.konan.target.HostManager
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
@@ -34,7 +33,6 @@ import java.nio.file.Files
|
|||||||
|
|
||||||
class NativeCompilerDownloader(
|
class NativeCompilerDownloader(
|
||||||
val project: Project,
|
val project: Project,
|
||||||
private val compilerVersion: String = project.konanVersion,
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -46,27 +44,36 @@ class NativeCompilerDownloader(
|
|||||||
|
|
||||||
internal const val BASE_DOWNLOAD_URL = "https://download.jetbrains.com/kotlin/native/builds"
|
internal const val BASE_DOWNLOAD_URL = "https://download.jetbrains.com/kotlin/native/builds"
|
||||||
internal const val KOTLIN_GROUP_ID = "org.jetbrains.kotlin"
|
internal const val KOTLIN_GROUP_ID = "org.jetbrains.kotlin"
|
||||||
}
|
|
||||||
|
|
||||||
val compilerDirectory: File
|
internal fun getCompilerDependencyNotation(project: Project): Map<String, String> {
|
||||||
get() = DependencyDirectories
|
return mapOf(
|
||||||
.getLocalKonanDir(project.konanDataDir)
|
"group" to KOTLIN_GROUP_ID,
|
||||||
.resolve(dependencyNameWithOsAndVersion)
|
"name" to getDependencyName(project),
|
||||||
|
"version" to getCompilerVersion(project),
|
||||||
|
"classifier" to simpleOsName,
|
||||||
|
"ext" to archiveExtension
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private val logger: Logger
|
internal fun getCompilerDirectory(project: Project): File {
|
||||||
get() = project.logger
|
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
|
private val simpleOsName = HostManager.platformName()
|
||||||
get() = HostManager.platformName()
|
|
||||||
|
|
||||||
private val dependencyName: String
|
private fun getCompilerVersion(project: Project): String {
|
||||||
get() {
|
return project.konanVersion
|
||||||
val dependencySuffix = distributionType.suffix
|
}
|
||||||
|
|
||||||
|
private fun getDependencyName(project: Project): String {
|
||||||
|
val dependencySuffix = NativeDistributionTypeProvider(project).getDistributionType().suffix
|
||||||
return if (dependencySuffix != null) {
|
return if (dependencySuffix != null) {
|
||||||
"kotlin-native-$dependencySuffix"
|
"kotlin-native-$dependencySuffix"
|
||||||
} else {
|
} 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
|
private val dependencyNameWithOsAndVersion: String
|
||||||
get() = "$dependencyName-$simpleOsName-$compilerVersion"
|
get() = getDependencyNameWithOsAndVersion(project)
|
||||||
|
|
||||||
private val dependencyFileName: String
|
private val dependencyFileName: String
|
||||||
get() = "$dependencyNameWithOsAndVersion.$archiveExtension"
|
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 =
|
private fun archiveFileTree(archive: File): FileTree =
|
||||||
if (useZip) {
|
if (useZip) {
|
||||||
project.zipTree(archive)
|
project.zipTree(archive)
|
||||||
@@ -114,11 +131,11 @@ class NativeCompilerDownloader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val repoUrl by lazy {
|
private val repoUrl by lazy {
|
||||||
val maturity = KotlinToolingVersion(compilerVersion).maturity
|
val maturity = KotlinToolingVersion(getCompilerVersion(project)).maturity
|
||||||
buildString {
|
buildString {
|
||||||
append("${kotlinProperties.nativeBaseDownloadUrl}/")
|
append("${kotlinProperties.nativeBaseDownloadUrl}/")
|
||||||
append(if (maturity == KotlinToolingVersion.Maturity.DEV) "dev/" else "releases/")
|
append(if (maturity == KotlinToolingVersion.Maturity.DEV) "dev/" else "releases/")
|
||||||
append("$compilerVersion/")
|
append("${getCompilerVersion(project)}/")
|
||||||
append(simpleOsName)
|
append(simpleOsName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,27 +146,19 @@ class NativeCompilerDownloader(
|
|||||||
} else null
|
} else null
|
||||||
|
|
||||||
val compilerDependency = if (kotlinProperties.nativeDownloadFromMaven) {
|
val compilerDependency = if (kotlinProperties.nativeDownloadFromMaven) {
|
||||||
project.dependencies.create(
|
project.dependencies.create(getCompilerDependencyNotation(project))
|
||||||
mapOf(
|
|
||||||
"group" to KOTLIN_GROUP_ID,
|
|
||||||
"name" to dependencyName,
|
|
||||||
"version" to compilerVersion,
|
|
||||||
"classifier" to simpleOsName,
|
|
||||||
"ext" to archiveExtension
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
project.dependencies.create(
|
project.dependencies.create(
|
||||||
mapOf(
|
mapOf(
|
||||||
"name" to "$dependencyName-$simpleOsName",
|
"name" to "${getDependencyName(project)}-$simpleOsName",
|
||||||
"version" to compilerVersion,
|
"version" to getCompilerVersion(project),
|
||||||
"ext" to archiveExtension
|
"ext" to archiveExtension
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val configuration = project.configurations.detachedResolvable(compilerDependency)
|
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) {
|
if (!kotlinProperties.nativeDownloadFromMaven) {
|
||||||
val dependencyUrl = "$repoUrl/$dependencyFileName"
|
val dependencyUrl = "$repoUrl/$dependencyFileName"
|
||||||
@@ -162,6 +171,12 @@ class NativeCompilerDownloader(
|
|||||||
configuration.files.single()
|
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.kotlinInfo("Using Kotlin/Native compiler archive: ${archive.absolutePath}")
|
||||||
|
|
||||||
logger.lifecycle("Unpack Kotlin/Native compiler to $compilerDirectory")
|
logger.lifecycle("Unpack Kotlin/Native compiler to $compilerDirectory")
|
||||||
@@ -186,8 +201,6 @@ class NativeCompilerDownloader(
|
|||||||
tmpDir.deleteRecursively()
|
tmpDir.deleteRecursively()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repo != null) removeRepo(repo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun downloadIfNeeded() {
|
fun downloadIfNeeded() {
|
||||||
@@ -199,11 +212,12 @@ class NativeCompilerDownloader(
|
|||||||
|
|
||||||
private fun checkClassPath() {
|
private fun checkClassPath() {
|
||||||
project.providers.of(NativeCompilerDownloaderClassPathChecker::class.java) {
|
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()
|
}.usedAtConfigurationTime(project.configurationTimePropertiesAccessor).get()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class NativeCompilerDownloaderClassPathChecker : ValueSource<Boolean, NativeCompilerDownloaderClassPathChecker.Params> {
|
internal abstract class NativeCompilerDownloaderClassPathChecker :
|
||||||
|
ValueSource<Boolean, NativeCompilerDownloaderClassPathChecker.Params> {
|
||||||
|
|
||||||
interface Params : ValueSourceParameters {
|
interface Params : ValueSourceParameters {
|
||||||
val classPath: ConfigurableFileCollection
|
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) {
|
internal fun Project.setupNativeCompiler(konanTarget: KonanTarget) {
|
||||||
val isKonanHomeOverridden = kotlinPropertiesProvider.nativeHome != null
|
val isKonanHomeOverridden = kotlinPropertiesProvider.nativeHome != null
|
||||||
if (!isKonanHomeOverridden) {
|
if (!isKonanHomeOverridden) {
|
||||||
@@ -227,9 +254,9 @@ internal fun Project.setupNativeCompiler(konanTarget: KonanTarget) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
downloader.downloadIfNeeded()
|
downloader.downloadIfNeeded()
|
||||||
logger.info("Kotlin/Native distribution: $konanHome")
|
logger.info("Kotlin/Native distribution: ${konanHome.absolutePath}")
|
||||||
} else {
|
} else {
|
||||||
logger.info("User-provided Kotlin/Native distribution: $konanHome")
|
logger.info("User-provided Kotlin/Native distribution: ${konanHome.absolutePath}")
|
||||||
}
|
}
|
||||||
|
|
||||||
val distributionType = NativeDistributionTypeProvider(project).getDistributionType()
|
val distributionType = NativeDistributionTypeProvider(project).getDistributionType()
|
||||||
|
|||||||
+3
-3
@@ -29,7 +29,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
internal class PlatformLibrariesGenerator(val project: Project, val konanTarget: KonanTarget) {
|
internal class PlatformLibrariesGenerator(val project: Project, val konanTarget: KonanTarget) {
|
||||||
|
|
||||||
private val distribution =
|
private val distribution =
|
||||||
customerDistribution(project.konanHome, konanDataDir = project.konanDataDir)
|
customerDistribution(project.konanHome.absolutePath, konanDataDir = project.konanDataDir)
|
||||||
|
|
||||||
private val platformLibsDirectory =
|
private val platformLibsDirectory =
|
||||||
File(distribution.platformLibs(konanTarget)).absoluteFile
|
File(distribution.platformLibs(konanTarget)).absoluteFile
|
||||||
@@ -77,7 +77,7 @@ internal class PlatformLibrariesGenerator(val project: Project, val konanTarget:
|
|||||||
}
|
}
|
||||||
|
|
||||||
val cacheDirectory = CacheBuilder.getRootCacheDirectory(
|
val cacheDirectory = CacheBuilder.getRootCacheDirectory(
|
||||||
File(project.konanHome), konanTarget, true, konanCacheKind
|
project.konanHome, konanTarget, true, konanCacheKind
|
||||||
)
|
)
|
||||||
return presentDefs.toPlatformLibNames().all {
|
return presentDefs.toPlatformLibNames().all {
|
||||||
cacheDirectory.resolve(CacheBuilder.getCacheFileName(it, konanCacheKind)).listFilesOrEmpty().isNotEmpty()
|
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-kind", konanCacheKind.produce!!)
|
||||||
args.addArg(
|
args.addArg(
|
||||||
"-cache-directory",
|
"-cache-directory",
|
||||||
CacheBuilder.getRootCacheDirectory(File(konanHome), konanTarget, true, konanCacheKind).absolutePath
|
CacheBuilder.getRootCacheDirectory(konanHome, konanTarget, true, konanCacheKind).absolutePath
|
||||||
)
|
)
|
||||||
args.addArg("-cache-arg", "-g")
|
args.addArg("-cache-arg", "-g")
|
||||||
val additionalCacheFlags = konanPropertiesService.additionalCacheFlags(konanTarget)
|
val additionalCacheFlags = konanPropertiesService.additionalCacheFlags(konanTarget)
|
||||||
|
|||||||
+45
-15
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf
|
|||||||
import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService
|
import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.UsesKonanPropertiesBuildService
|
import org.jetbrains.kotlin.gradle.targets.native.UsesKonanPropertiesBuildService
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.CompilerPluginData
|
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.gradle.utils.*
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
@@ -62,14 +63,6 @@ constructor(
|
|||||||
val compilation: KotlinNativeCompilation
|
val compilation: KotlinNativeCompilation
|
||||||
get() = binary.compilation
|
get() = binary.compilation
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
val konanDataDir: Provider<String?> = project.provider { project.konanDataDir }
|
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
val konanHome: Provider<String> = project.provider { project.konanHome }
|
|
||||||
|
|
||||||
private val runnerSettings = KotlinNativeCompilerRunner.Settings.of(konanHome.get(), konanDataDir.getOrNull(), project)
|
|
||||||
|
|
||||||
final override val toolOptions: KotlinCommonCompilerToolOptions = objectFactory
|
final override val toolOptions: KotlinCommonCompilerToolOptions = objectFactory
|
||||||
.newInstance<KotlinCommonCompilerToolOptionsDefault>()
|
.newInstance<KotlinCommonCompilerToolOptionsDefault>()
|
||||||
|
|
||||||
@@ -206,17 +199,29 @@ constructor(
|
|||||||
private val externalDependenciesArgs by lazy { ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() }
|
private val externalDependenciesArgs by lazy { ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() }
|
||||||
|
|
||||||
private val cacheBuilderSettings by lazy {
|
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,
|
private class CacheSettings(
|
||||||
val icEnabled: Boolean, val threads: Int,
|
val orchestration: NativeCacheOrchestration, val kind: NativeCacheKind,
|
||||||
val gradleUserHomeDir: File, val gradleBuildDir: File)
|
val icEnabled: Boolean, val threads: Int,
|
||||||
|
val gradleUserHomeDir: File, val gradleBuildDir: File,
|
||||||
|
)
|
||||||
|
|
||||||
private val cacheSettings by lazy {
|
private val cacheSettings by lazy {
|
||||||
CacheSettings(project.getKonanCacheOrchestration(), project.getKonanCacheKind(konanTarget),
|
CacheSettings(
|
||||||
project.isKonanIncrementalCompilationEnabled(), project.getKonanParallelThreads(),
|
project.getKonanCacheOrchestration(), project.getKonanCacheKind(konanTarget),
|
||||||
project.gradle.gradleUserHomeDir, project.layout.buildDirectory.get().asFile)
|
project.isKonanIncrementalCompilationEnabled(), project.getKonanParallelThreads(),
|
||||||
|
project.gradle.gradleUserHomeDir, project.layout.buildDirectory.get().asFile
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createCompilerArguments(context: CreateCompilerArgumentsContext) = context.create<K2NativeCompilerArguments> {
|
override fun createCompilerArguments(context: CreateCompilerArgumentsContext) = context.create<K2NativeCompilerArguments> {
|
||||||
@@ -343,6 +348,31 @@ constructor(
|
|||||||
@get:Nested
|
@get:Nested
|
||||||
var kotlinPluginData: Provider<KotlinCompilerPluginData>? = null
|
var kotlinPluginData: Provider<KotlinCompilerPluginData>? = null
|
||||||
|
|
||||||
|
@get:Nested
|
||||||
|
internal val kotlinNativeProvider: Provider<KotlinNativeProvider> = 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<String?> = 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<String> = kotlinNativeProvider.map { it.bundleDirectory.get().asFile.absolutePath }
|
||||||
|
|
||||||
|
private val runnerSettings = KotlinNativeCompilerRunner.Settings.of(
|
||||||
|
kotlinNativeProvider.get().bundleDirectory.getFile().absolutePath,
|
||||||
|
kotlinNativeProvider.get().konanDataDir.orNull,
|
||||||
|
project
|
||||||
|
)
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun compile() {
|
fun compile() {
|
||||||
val metricsReporter = metrics.get()
|
val metricsReporter = metrics.get()
|
||||||
|
|||||||
+43
-14
@@ -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.mpp.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.UsesBuildFusService
|
import org.jetbrains.kotlin.gradle.plugin.statistics.UsesBuildFusService
|
||||||
import org.jetbrains.kotlin.gradle.report.*
|
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.KonanPropertiesBuildService
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.*
|
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.*
|
||||||
import org.jetbrains.kotlin.gradle.utils.GradleLoggerAdapter
|
import org.jetbrains.kotlin.gradle.utils.GradleLoggerAdapter
|
||||||
import org.jetbrains.kotlin.gradle.utils.listFilesOrEmpty
|
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.
|
* 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
|
@get:Internal // these sources are normally a subset of `source` ones which are already tracked
|
||||||
val commonSources: ConfigurableFileCollection = project.files()
|
val commonSources: ConfigurableFileCollection = project.files()
|
||||||
|
|
||||||
@get:Internal
|
@get:Nested
|
||||||
val konanDataDir: Provider<String?> = project.provider { project.konanDataDir }
|
internal val kotlinNativeProvider: Provider<KotlinNativeProvider> = 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
|
@get:Internal
|
||||||
val konanHome: Provider<String> = project.provider { project.konanHome }
|
val konanDataDir: Provider<String?> = 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<String> = kotlinNativeProvider.map { it.bundleDirectory.get().asFile.absolutePath }
|
||||||
|
|
||||||
@get:Nested
|
@get:Nested
|
||||||
override val multiplatformStructure: K2MultiplatformStructure = objectFactory.newInstance()
|
override val multiplatformStructure: K2MultiplatformStructure = objectFactory.newInstance()
|
||||||
@@ -410,7 +418,11 @@ internal constructor(
|
|||||||
override val additionalCompilerOptions: Provider<Collection<String>>
|
override val additionalCompilerOptions: Provider<Collection<String>>
|
||||||
get() = compilerOptions.freeCompilerArgs as Provider<Collection<String>>
|
get() = compilerOptions.freeCompilerArgs as Provider<Collection<String>>
|
||||||
|
|
||||||
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.
|
// endregion.
|
||||||
|
|
||||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||||
@@ -1077,13 +1089,30 @@ abstract class CInteropProcess @Inject internal constructor(params: Params) :
|
|||||||
val outputFile: File
|
val outputFile: File
|
||||||
get() = outputFileProvider.get()
|
get() = outputFileProvider.get()
|
||||||
|
|
||||||
@get:Internal
|
@get:Nested
|
||||||
val konanDataDir: Provider<String?> = project.provider { project.konanDataDir }
|
internal val kotlinNativeProvider: Provider<KotlinNativeProvider> = 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
|
@get:Internal
|
||||||
val konanHome: Provider<String> = project.provider { project.konanHome }
|
val konanDataDir: Provider<String?> = 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<String> = 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.
|
// Inputs and outputs.
|
||||||
|
|
||||||
@OutputFile
|
@OutputFile
|
||||||
|
|||||||
+24
-7
@@ -23,10 +23,8 @@ import org.gradle.work.DisableCachingByDefault
|
|||||||
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
|
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
|
||||||
import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric
|
import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric
|
||||||
import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime
|
import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.*
|
||||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeCompilerRunner
|
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.compilerRunner.addBuildMetricsForTaskAction
|
||||||
import org.jetbrains.kotlin.gradle.dsl.*
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated
|
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.GradleBuildMetricsReporter
|
||||||
import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService
|
import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.buildKotlinNativeBinaryLinkerArgs
|
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.tasks.KotlinToolTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.XcodeUtils
|
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.newInstance
|
||||||
import org.jetbrains.kotlin.gradle.utils.property
|
import org.jetbrains.kotlin.gradle.utils.property
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
@@ -170,13 +170,30 @@ abstract class KotlinNativeLinkArtifactTask @Inject constructor(
|
|||||||
val metrics: Property<BuildMetricsReporter<GradleBuildTime, GradleBuildPerformanceMetric>> = project.objects
|
val metrics: Property<BuildMetricsReporter<GradleBuildTime, GradleBuildPerformanceMetric>> = project.objects
|
||||||
.property(GradleBuildMetricsReporter())
|
.property(GradleBuildMetricsReporter())
|
||||||
|
|
||||||
@get:Internal
|
@get:Nested
|
||||||
val konanDataDir: Provider<String?> = project.provider { project.konanDataDir }
|
internal val kotlinNativeProvider: Provider<KotlinNativeProvider> = 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
|
@get:Internal
|
||||||
val konanHome: Provider<String> = project.provider { project.konanHome }
|
val konanDataDir: Provider<String?> = 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<String> = kotlinNativeProvider.map { it.bundleDirectory.get().asFile.absolutePath }
|
||||||
|
|
||||||
|
private val runnerSettings = KotlinNativeCompilerRunner.Settings.of(
|
||||||
|
kotlinNativeProvider.get().bundleDirectory.getFile().absolutePath,
|
||||||
|
kotlinNativeProvider.get().konanDataDir.orNull,
|
||||||
|
project
|
||||||
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
baseName.convention(project.name)
|
baseName.convention(project.name)
|
||||||
|
|||||||
+57
@@ -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<KotlinNativeBundleArtifactsTypes> =
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+110
@@ -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<String?> = project.provider { project.konanDataDir }
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
val bundleDirectory: DirectoryProperty = project.objects.directoryProperty().fileProvider(
|
||||||
|
project.provider {
|
||||||
|
project.konanHome
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
val reinstallBundle: Property<Boolean> = project.objects.property(project.kotlinPropertiesProvider.nativeReinstall)
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
internal val kotlinNativeBundleVersion: Provider<String> = 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+59
@@ -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<TransformParameters.None> {
|
||||||
|
|
||||||
|
@get:Inject
|
||||||
|
abstract val archiveOperations: ArchiveOperations
|
||||||
|
|
||||||
|
@get:Inject
|
||||||
|
abstract val fileSystemOperations: FileSystemOperations
|
||||||
|
|
||||||
|
@get:InputArtifact
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
|
abstract val inputArtifact: Provider<FileSystemLocation>
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,9 +20,6 @@ internal val konanHome: File by lazy {
|
|||||||
.run {
|
.run {
|
||||||
project.plugins.apply("kotlin-multiplatform")
|
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 {
|
(project.kotlinExtension as KotlinMultiplatformExtension).apply {
|
||||||
macosX64()
|
macosX64()
|
||||||
macosArm64()
|
macosArm64()
|
||||||
|
|||||||
Reference in New Issue
Block a user