Skip to content

Commit

Permalink
[Gradle, native] Disable platform libraries generation by default
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ilmat192 committed Apr 17, 2020
1 parent 7ee4f48 commit 2938b69
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
fun testNoGenerationForOldCompiler() = with(platformLibrariesProject("linuxX64")) {
deleteInstalledCompilers()

// 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.
build("tasks", "-Pkotlin.native.version=1.3.60") {
build("tasks", "-Pkotlin.native.version=$oldCompilerVersion") {
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 ")
}
}
Expand All @@ -66,14 +83,15 @@ class NativePlatformLibsIT : BaseGradleIT() {

with(rootProject) {
// Check that platform libraries are correctly generated for both root project and a subproject.
build("assemble") {
buildWithLightDist("assemble") {
assertSuccessful()
assertContainsRegex("Kotlin/Native distribution: .*kotlin-native-(macos|linux|windows)".toRegex())
assertContains("Generate platform libraries for linux_x64")
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.
build("assemble") {
buildWithLightDist("assemble") {
assertSuccessful()
assertNotContains("Generate platform libraries for ")
}
Expand All @@ -89,7 +107,7 @@ class NativePlatformLibsIT : BaseGradleIT() {
else -> KonanTarget.IOS_X64
}

platformLibrariesProject(unsupportedTarget.presetName).build("assemble") {
platformLibrariesProject(unsupportedTarget.presetName).buildWithLightDist("assemble") {
assertSuccessful()
assertNotContains("Generate platform libraries for ")
}
Expand All @@ -104,13 +122,13 @@ class NativePlatformLibsIT : BaseGradleIT() {

with(platformLibrariesProject("iosX64")) {
// Build Mac libraries without caches.
build("tasks") {
buildWithLightDist("tasks") {
assertSuccessful()
assertContains("Generate platform libraries for ios_x64")
}

// Change cache kind and check that platform libraries generator was executed.
build("tasks", "-Pkotlin.native.cacheKind=static") {
buildWithLightDist("tasks", "-Pkotlin.native.cacheKind=static") {
assertSuccessful()
assertContains("Precompile platform libraries for ios_x64 (precompilation: static)")
}
Expand All @@ -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
fun testSettingGenerationMode() = with(platformLibrariesProject("linuxX64")) {
deleteInstalledCompilers()

// 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()
assertContainsRegex("Run tool: \"generatePlatformLibraries\" with args: .* -mode metadata".toRegex())
}
Expand All @@ -144,13 +203,13 @@ class NativePlatformLibsIT : BaseGradleIT() {
deleteInstalledCompilers()

// Install the compiler at the first time. Don't build to reduce execution time.
build("tasks") {
buildWithLightDist("tasks") {
assertSuccessful()
assertContains("Generate platform libraries for linux_x64")
}

// Reinstall the compiler.
build("tasks", "-Pkotlin.native.reinstall=true") {
buildWithLightDist("tasks", "-Pkotlin.native.reinstall=true") {
assertSuccessful()
assertContains("Unpack Kotlin/Native compiler to ")
assertContains("Generate platform libraries for linux_x64")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.KotlinJsSingleTargetPreset
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.dsl.KotlinJsTargetDsl
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrSingleTargetPreset
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.KonanTarget
import kotlin.reflect.KClass

private const val KOTLIN_PROJECT_EXTENSION_NAME = "kotlin"
Expand Down Expand Up @@ -239,24 +236,3 @@ enum class ExplicitApiMode(private val cliOption: String) {

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) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.Coroutines
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.targets.native.DisabledNativeTargetsReporter
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
Expand Down Expand Up @@ -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:
* - regular - The default distribution. Includes all platform libraries in 1.3 and generates them at the user side in 1.4.
* - restricted - Doesn't include Apple platform libraries. Available for MacOS only and in 1.3 only.
* - prebuilt - Includes all platform libraries. Available in 1.4 only. Used to workaround possible problems with library generation at the use side.
* - light - Doesn't include platform libraries and generates them at the user side. For 1.3 corresponds to the restricted distribution.
* - prebuilt - Includes all platform libraries.
*/
val nativeDistributionType: NativeDistributionType?
get() {
var result = property("kotlin.native.distribution.type")?.let {
NativeDistributionType.byCompilerArgument(it)
}

val deprecatedRestricted = booleanProperty("kotlin.native.restrictedDistribution")
if (result == null && deprecatedRestricted != null) {
SingleWarningPerBuild.show(
project,
"Project property 'kotlin.native.restrictedDistribution' is deprecated. Please use 'kotlin.native.distribution.type=restricted' instead"
)
result = if (deprecatedRestricted) NativeDistributionType.RESTRICTED else NativeDistributionType.LIGHT
}
val nativeDistributionType: String?
get() = property("kotlin.native.distribution.type")

return result
}
/**
* A property that was used to choose a restricted distribution in 1.3.
*/
val nativeDeprecatedRestricted: Boolean?
get() = booleanProperty("kotlin.native.restrictedDistribution")

/**
* Allows a user to force a particular cinterop mode for platform libraries generation. Available modes: sourcecode, metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import org.gradle.api.Project
import org.gradle.api.invocation.Gradle
import org.jetbrains.kotlin.compilerRunner.konanHome
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.PropertiesProvider
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.setUpKotlinNativePlatformDependencies
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
Expand Down Expand Up @@ -64,10 +64,8 @@ abstract class AbstractKotlinNativeTargetPreset<T : KotlinNativeTarget>(
logger.info("User-provided Kotlin/Native distribution: $konanHome")
}

val distributionType = PropertiesProvider(project).nativeDistributionType
if (konanVersion.isAtLeast(1, 4, 0) &&
(distributionType == null || distributionType == LIGHT)
) {
val distributionType = NativeDistributionTypeProvider(project).getDistributionType(konanVersion)
if (distributionType.mustGeneratePlatformLibs) {
PlatformLibrariesGenerator(project, konanTarget).generatePlatformLibsIfNeeded()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import org.gradle.api.file.FileTree
import org.gradle.api.logging.Logger
import org.jetbrains.kotlin.compilerRunner.KotlinNativeCompilerRunner
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.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.MetaVersion
import org.jetbrains.kotlin.konan.target.HostManager
Expand All @@ -41,9 +41,7 @@ class NativeCompilerDownloader(
get() = project.logger

private val distributionType: NativeDistributionType
get() = PropertiesProvider(project).nativeDistributionType?.takeIf {
it.isAvailableFor(HostManager.host, compilerVersion)
} ?: NativeDistributionType.LIGHT
get() = NativeDistributionTypeProvider(project).getDistributionType(compilerVersion)

private val simpleOsName: String
get() = HostManager.simpleOsName()
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
}

0 comments on commit 2938b69

Please sign in to comment.