From 2938b69ff5a68149ccf379086eb6c7091a1ffcf8 Mon Sep 17 00:00:00 2001 From: Ilya Matveev Date: Wed, 8 Apr 2020 20:10:10 +0700 Subject: [PATCH] [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 --- .../kotlin/gradle/NativePlatformLibsIT.kt | 77 ++++++++++++++++--- .../gradle/dsl/KotlinProjectExtension.kt | 24 ------ .../kotlin/gradle/plugin/KotlinProperties.kt | 29 +++---- .../native/KotlinNativeTargetPreset.kt | 8 +- .../native/NativeCompilerDownloader.kt | 8 +- .../native/internal/NativeDistributionType.kt | 76 ++++++++++++++++++ 6 files changed, 159 insertions(+), 63 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/NativeDistributionType.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NativePlatformLibsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NativePlatformLibsIT.kt index 435ba2c8296..84c2497742f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NativePlatformLibsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NativePlatformLibsIT.kt @@ -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 ") } } @@ -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 ") } @@ -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 ") } @@ -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)") } @@ -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()) } @@ -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") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt index 6f899b4725c..4baf36cff2a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt @@ -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" @@ -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) } - } -} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt index 80d15754e3f..8d90307d862 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt @@ -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 @@ -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 nativeDistributionType: String? + get() = property("kotlin.native.distribution.type") - 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 - } - - 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. diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt index 0770c925dea..a019162945f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt @@ -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 @@ -64,10 +64,8 @@ abstract class AbstractKotlinNativeTargetPreset( 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() } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt index afd13b39f67..e96f85e5c52 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/NativeCompilerDownloader.kt @@ -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 @@ -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() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/NativeDistributionType.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/NativeDistributionType.kt new file mode 100644 index 00000000000..0140d5efd86 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/NativeDistributionType.kt @@ -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) + } + } +}