[Gradle, native] Disable platform libraries generation by default

Since there are a lot of changes around klibs in 1.4-M2, it was
decided to postpone enabling user-side platform libraries generation
by default. This patch switches the default distribution type to
prebuilt.

It also slightly refactors the code allowing user to choose the
distribution type. Now, there are only two distribution types
available:

- prebuilt - the default type, contains prebuilt platform libs.
             A distribution archive has the "-prebuilt-" classifier.
- light    - doesn't contain platform libs in an archive and
             generates them at the user side. The archive has no
             classifier to avoid changes in the K/N build logic and
             TC configurations.

The same types are also available for 1.3 but with sightly different
convention:

- prebuilt - the default type, contains prebuilt platform libs.
             A distribution archive has no classifier.
- light    - aka "restricted" distribution, doesn't contain
             platform libs for Apple platforms. The archive has
             the "-restricted-" suffix. Doesn't have a facility
             to build the libraries at the user side.

Issue #KT-38174 Fixed
This commit is contained in:
Ilya Matveev
2020-04-08 20:10:10 +07:00
parent 7ee4f4853d
commit 2938b69ff5
6 changed files with 159 additions and 63 deletions
@@ -40,14 +40,31 @@ class NativePlatformLibsIT : BaseGradleIT() {
} }
} }
private fun BaseGradleIT.Project.buildWithLightDist(vararg tasks: String, check: CompiledProject.() -> Unit) =
build(*tasks, "-Pkotlin.native.distribution.type=light", check = check)
@Test @Test
fun testNoGenerationForOldCompiler() = with(platformLibrariesProject("linuxX64")) { fun testNoGenerationForOldCompiler() = with(platformLibrariesProject("linuxX64")) {
deleteInstalledCompilers() deleteInstalledCompilers()
// Check that we don't run the library generator for old compiler distributions where libraries are prebuilt. // Check that we don't run the library generator for old compiler distributions where libraries are prebuilt.
// Don't run the build to reduce execution time. // Don't run the build to reduce execution time.
build("tasks", "-Pkotlin.native.version=1.3.60") { build("tasks", "-Pkotlin.native.version=$oldCompilerVersion") {
assertSuccessful() assertSuccessful()
assertContains("Unpack Kotlin/Native compiler to ")
assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-(macos|linux|windows)".toRegex())
assertNotContains("Generate platform libraries for ")
}
}
@Test
fun testNoGenerationByDefault() = with(platformLibrariesProject("linuxX64")) {
deleteInstalledCompilers()
// Check that a prebuilt distribution is used by default.
build("assemble") {
assertSuccessful()
assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-prebuilt-(macos|linux|windows)".toRegex())
assertNotContains("Generate platform libraries for ") assertNotContains("Generate platform libraries for ")
} }
} }
@@ -66,14 +83,15 @@ class NativePlatformLibsIT : BaseGradleIT() {
with(rootProject) { with(rootProject) {
// Check that platform libraries are correctly generated for both root project and a subproject. // Check that platform libraries are correctly generated for both root project and a subproject.
build("assemble") { buildWithLightDist("assemble") {
assertSuccessful() assertSuccessful()
assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-(macos|linux|windows)".toRegex())
assertContains("Generate platform libraries for linux_x64") assertContains("Generate platform libraries for linux_x64")
assertContains("Generate platform libraries for linux_arm64") assertContains("Generate platform libraries for linux_arm64")
} }
// Check that we don't generate libraries during a second run. Don't clean to reduce execution time. // Check that we don't generate libraries during a second run. Don't clean to reduce execution time.
build("assemble") { buildWithLightDist("assemble") {
assertSuccessful() assertSuccessful()
assertNotContains("Generate platform libraries for ") assertNotContains("Generate platform libraries for ")
} }
@@ -89,7 +107,7 @@ class NativePlatformLibsIT : BaseGradleIT() {
else -> KonanTarget.IOS_X64 else -> KonanTarget.IOS_X64
} }
platformLibrariesProject(unsupportedTarget.presetName).build("assemble") { platformLibrariesProject(unsupportedTarget.presetName).buildWithLightDist("assemble") {
assertSuccessful() assertSuccessful()
assertNotContains("Generate platform libraries for ") assertNotContains("Generate platform libraries for ")
} }
@@ -104,13 +122,13 @@ class NativePlatformLibsIT : BaseGradleIT() {
with(platformLibrariesProject("iosX64")) { with(platformLibrariesProject("iosX64")) {
// Build Mac libraries without caches. // Build Mac libraries without caches.
build("tasks") { buildWithLightDist("tasks") {
assertSuccessful() assertSuccessful()
assertContains("Generate platform libraries for ios_x64") assertContains("Generate platform libraries for ios_x64")
} }
// Change cache kind and check that platform libraries generator was executed. // Change cache kind and check that platform libraries generator was executed.
build("tasks", "-Pkotlin.native.cacheKind=static") { buildWithLightDist("tasks", "-Pkotlin.native.cacheKind=static") {
assertSuccessful() assertSuccessful()
assertContains("Precompile platform libraries for ios_x64 (precompilation: static)") assertContains("Precompile platform libraries for ios_x64 (precompilation: static)")
} }
@@ -128,12 +146,53 @@ class NativePlatformLibsIT : BaseGradleIT() {
} }
} }
@Test
fun testDeprecatedRestrictedDistributionProperty() = with(platformLibrariesProject("linuxX64")) {
build("tasks", "-Pkotlin.native.restrictedDistribution=true", "-Pkotlin.native.version=$oldCompilerVersion") {
assertSuccessful()
assertContains("Warning: Project property 'kotlin.native.restrictedDistribution' is deprecated. Please use 'kotlin.native.distribution.type=light' instead")
// Restricted distribution is available for Mac hosts only.
if (HostManager.hostIsMac) {
assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-restricted-(macos|linux|windows)".toRegex())
} else {
assertNotContains("Kotlin/Native distribution: .*kotlin-native-restricted-(macos|linux|windows)".toRegex())
}
}
// We allow using this deprecated property for 1.4 too. Just download the distribution without platform libs in this case.
build("tasks", "-Pkotlin.native.restrictedDistribution=true") {
assertSuccessful()
assertContains("Warning: Project property 'kotlin.native.restrictedDistribution' is deprecated. Please use 'kotlin.native.distribution.type=light' instead")
assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-(macos|linux|windows)".toRegex())
}
}
@Test
fun testSettingDistributionTypeForOldCompiler() = with(platformLibrariesProject("linuxX64")) {
build("tasks", "-Pkotlin.native.distribution.type=prebuilt", "-Pkotlin.native.version=$oldCompilerVersion") {
assertSuccessful()
assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-(macos|linux|windows)".toRegex())
}
build("tasks", "-Pkotlin.native.distribution.type=light", "-Pkotlin.native.version=$oldCompilerVersion") {
assertSuccessful()
// Restricted distribution is available for Mac hosts only.
if (HostManager.hostIsMac) {
assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-restricted-(macos|linux|windows)".toRegex())
} else {
assertNotContains("Kotlin/Native distribution: .*kotlin-native-restricted-(macos|linux|windows)".toRegex())
}
}
}
@Test @Test
fun testSettingGenerationMode() = with(platformLibrariesProject("linuxX64")) { fun testSettingGenerationMode() = with(platformLibrariesProject("linuxX64")) {
deleteInstalledCompilers() deleteInstalledCompilers()
// Check that user can change generation mode used by the cinterop tool. // Check that user can change generation mode used by the cinterop tool.
build("tasks", "-Pkotlin.native.platform.libraries.mode=metadata") { buildWithLightDist("tasks", "-Pkotlin.native.platform.libraries.mode=metadata") {
assertSuccessful() assertSuccessful()
assertContainsRegex("Run tool: \"generatePlatformLibraries\" with args: .* -mode metadata".toRegex()) assertContainsRegex("Run tool: \"generatePlatformLibraries\" with args: .* -mode metadata".toRegex())
} }
@@ -144,13 +203,13 @@ class NativePlatformLibsIT : BaseGradleIT() {
deleteInstalledCompilers() deleteInstalledCompilers()
// Install the compiler at the first time. Don't build to reduce execution time. // Install the compiler at the first time. Don't build to reduce execution time.
build("tasks") { buildWithLightDist("tasks") {
assertSuccessful() assertSuccessful()
assertContains("Generate platform libraries for linux_x64") assertContains("Generate platform libraries for linux_x64")
} }
// Reinstall the compiler. // Reinstall the compiler.
build("tasks", "-Pkotlin.native.reinstall=true") { buildWithLightDist("tasks", "-Pkotlin.native.reinstall=true") {
assertSuccessful() assertSuccessful()
assertContains("Unpack Kotlin/Native compiler to ") assertContains("Unpack Kotlin/Native compiler to ")
assertContains("Generate platform libraries for linux_x64") assertContains("Generate platform libraries for linux_x64")
@@ -15,14 +15,11 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsSingleTargetPreset import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsSingleTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.isAtLeast
import org.jetbrains.kotlin.gradle.targets.js.calculateJsCompilerType import org.jetbrains.kotlin.gradle.targets.js.calculateJsCompilerType
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrSingleTargetPreset import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrSingleTargetPreset
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.CompilerVersion
import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.KonanTarget
import kotlin.reflect.KClass import kotlin.reflect.KClass
private const val KOTLIN_PROJECT_EXTENSION_NAME = "kotlin" private const val KOTLIN_PROJECT_EXTENSION_NAME = "kotlin"
@@ -239,24 +236,3 @@ enum class ExplicitApiMode(private val cliOption: String) {
fun toCompilerArg() = "-Xexplicit-api=$cliOption" fun toCompilerArg() = "-Xexplicit-api=$cliOption"
} }
enum class NativeDistributionType(val suffix: String?) {
LIGHT(null) {
override fun isAvailableFor(host: KonanTarget, version: CompilerVersion) = true
},
RESTRICTED("restricted") {
override fun isAvailableFor(host: KonanTarget, version: CompilerVersion): Boolean =
host == KonanTarget.MACOS_X64 && version.major == 1 && version.minor == 3
},
PREBUILT("prebuilt") {
override fun isAvailableFor(host: KonanTarget, version: CompilerVersion): Boolean =
version.isAtLeast(1, 4, 0)
};
abstract fun isAvailableFor(host: KonanTarget, version: CompilerVersion): Boolean
companion object {
fun byCompilerArgument(argument: String): NativeDistributionType? =
values().firstOrNull { it.name.equals(argument, ignoreCase = true) }
}
}
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.Coroutines import org.jetbrains.kotlin.gradle.dsl.Coroutines
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
import org.jetbrains.kotlin.gradle.dsl.NativeDistributionType
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompilerProperty import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompilerProperty
import org.jetbrains.kotlin.gradle.targets.native.DisabledNativeTargetsReporter import org.jetbrains.kotlin.gradle.targets.native.DisabledNativeTargetsReporter
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
@@ -126,27 +125,17 @@ internal class PropertiesProvider private constructor(private val project: Proje
/** /**
* Allow a user to choose distribution type. The following distribution types are available: * Allow a user to choose distribution type. The following distribution types are available:
* - regular - The default distribution. Includes all platform libraries in 1.3 and generates them at the user side in 1.4. * - light - Doesn't include platform libraries and generates them at the user side. For 1.3 corresponds to the restricted distribution.
* - restricted - Doesn't include Apple platform libraries. Available for MacOS only and in 1.3 only. * - prebuilt - Includes all platform libraries.
* - prebuilt - Includes all platform libraries. Available in 1.4 only. Used to workaround possible problems with library generation at the use side.
*/ */
val nativeDistributionType: NativeDistributionType? val nativeDistributionType: String?
get() { get() = property("kotlin.native.distribution.type")
var result = property("kotlin.native.distribution.type")?.let {
NativeDistributionType.byCompilerArgument(it)
}
val deprecatedRestricted = booleanProperty("kotlin.native.restrictedDistribution") /**
if (result == null && deprecatedRestricted != null) { * A property that was used to choose a restricted distribution in 1.3.
SingleWarningPerBuild.show( */
project, val nativeDeprecatedRestricted: Boolean?
"Project property 'kotlin.native.restrictedDistribution' is deprecated. Please use 'kotlin.native.distribution.type=restricted' instead" get() = booleanProperty("kotlin.native.restrictedDistribution")
)
result = if (deprecatedRestricted) NativeDistributionType.RESTRICTED else NativeDistributionType.LIGHT
}
return result
}
/** /**
* Allows a user to force a particular cinterop mode for platform libraries generation. Available modes: sourcecode, metadata. * Allows a user to force a particular cinterop mode for platform libraries generation. Available modes: sourcecode, metadata.
@@ -13,10 +13,10 @@ import org.gradle.api.Project
import org.gradle.api.invocation.Gradle import org.gradle.api.invocation.Gradle
import org.jetbrains.kotlin.compilerRunner.konanHome import org.jetbrains.kotlin.compilerRunner.konanHome
import org.jetbrains.kotlin.compilerRunner.konanVersion import org.jetbrains.kotlin.compilerRunner.konanVersion
import org.jetbrains.kotlin.gradle.dsl.NativeDistributionType.LIGHT
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.targets.native.DisabledNativeTargetsReporter import org.jetbrains.kotlin.gradle.targets.native.DisabledNativeTargetsReporter
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.gradle.targets.native.internal.setUpKotlinNativePlatformDependencies import org.jetbrains.kotlin.gradle.targets.native.internal.setUpKotlinNativePlatformDependencies
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
@@ -64,10 +64,8 @@ abstract class AbstractKotlinNativeTargetPreset<T : KotlinNativeTarget>(
logger.info("User-provided Kotlin/Native distribution: $konanHome") logger.info("User-provided Kotlin/Native distribution: $konanHome")
} }
val distributionType = PropertiesProvider(project).nativeDistributionType val distributionType = NativeDistributionTypeProvider(project).getDistributionType(konanVersion)
if (konanVersion.isAtLeast(1, 4, 0) && if (distributionType.mustGeneratePlatformLibs) {
(distributionType == null || distributionType == LIGHT)
) {
PlatformLibrariesGenerator(project, konanTarget).generatePlatformLibsIfNeeded() PlatformLibrariesGenerator(project, konanTarget).generatePlatformLibsIfNeeded()
} }
} }
@@ -12,9 +12,9 @@ import org.gradle.api.file.FileTree
import org.gradle.api.logging.Logger import org.gradle.api.logging.Logger
import org.jetbrains.kotlin.compilerRunner.KotlinNativeCompilerRunner import org.jetbrains.kotlin.compilerRunner.KotlinNativeCompilerRunner
import org.jetbrains.kotlin.compilerRunner.konanVersion import org.jetbrains.kotlin.compilerRunner.konanVersion
import org.jetbrains.kotlin.gradle.dsl.NativeDistributionType
import org.jetbrains.kotlin.gradle.logging.kotlinInfo import org.jetbrains.kotlin.gradle.logging.kotlinInfo
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.targets.native.internal.NativeDistributionType
import org.jetbrains.kotlin.gradle.targets.native.internal.NativeDistributionTypeProvider
import org.jetbrains.kotlin.konan.CompilerVersion import org.jetbrains.kotlin.konan.CompilerVersion
import org.jetbrains.kotlin.konan.MetaVersion import org.jetbrains.kotlin.konan.MetaVersion
import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.HostManager
@@ -41,9 +41,7 @@ class NativeCompilerDownloader(
get() = project.logger get() = project.logger
private val distributionType: NativeDistributionType private val distributionType: NativeDistributionType
get() = PropertiesProvider(project).nativeDistributionType?.takeIf { get() = NativeDistributionTypeProvider(project).getDistributionType(compilerVersion)
it.isAvailableFor(HostManager.host, compilerVersion)
} ?: NativeDistributionType.LIGHT
private val simpleOsName: String private val simpleOsName: String
get() = HostManager.simpleOsName() get() = HostManager.simpleOsName()
@@ -0,0 +1,76 @@
/*
* Copyright 2010-2020 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.internal
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.isAtLeast
import org.jetbrains.kotlin.gradle.targets.native.internal.NativeDistributionType.*
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
import org.jetbrains.kotlin.konan.CompilerVersion
import org.jetbrains.kotlin.konan.target.HostManager
internal enum class NativeDistributionType(val suffix: String?, val mustGeneratePlatformLibs: Boolean) {
LIGHT(null, true),
PREBUILT("prebuilt", false),
// Distribution types for 1.3:
LIGHT_1_3("restricted", false), // aka "restricted" distribution without platform libs for Apple targets.
PREBUILT_1_3(null, false)
}
internal class NativeDistributionTypeProvider(private val project: Project) {
private val propertiesProvider = PropertiesProvider(project)
private fun warning(message: String) = SingleWarningPerBuild.show(project, "Warning: $message")
private fun chooseDistributionType(
prebuiltType: NativeDistributionType,
lightType: NativeDistributionType,
defaultType: NativeDistributionType
): NativeDistributionType {
val requestedByUser = propertiesProvider.nativeDistributionType?.toLowerCase()
val deprecatedRestricted = propertiesProvider.nativeDeprecatedRestricted
// A case when a deprecated property (kotlin.native.restrictedDistribution) is used to choose the restricted distribution.
// Effectively the restricted distribution from 1.3 and the light distribution from 1.4 are the same,
// so we allow user to specify kotlin.native.restrictedDistribution in both 1.3 and 1.4
if (requestedByUser == null && deprecatedRestricted != null) {
return if (deprecatedRestricted) {
lightType
} else {
defaultType
}
}
// A normal path: no deprecated properties, only kotlin.native.distribution.type.
return when (requestedByUser) {
null -> defaultType
"prebuilt" -> prebuiltType
"light" -> lightType
else -> {
warning("Unknown Kotlin/Native distribution type: $requestedByUser. Available values: prebuilt, light")
defaultType
}
}
}
fun getDistributionType(version: CompilerVersion): NativeDistributionType {
if (propertiesProvider.nativeDeprecatedRestricted != null) {
warning("Project property 'kotlin.native.restrictedDistribution' is deprecated. Please use 'kotlin.native.distribution.type=light' instead")
}
return if (version.isAtLeast(1, 4, 0)) {
chooseDistributionType(prebuiltType = PREBUILT, lightType = LIGHT, defaultType = PREBUILT)
} else {
// In 1.3, the distribution type can be chosen for Mac hosts only.
if (!HostManager.hostIsMac) {
return PREBUILT_1_3
}
chooseDistributionType(prebuiltType = PREBUILT_1_3, lightType = LIGHT_1_3, defaultType = PREBUILT_1_3)
}
}
}