Drop Gradle < 6.0 support for Kotlin MPP Gradle plugin

This is required due to issues with dependency resolution of the
kotlinx library modules published in a way that their root MPP module
contains the JVM artifacts so that consumers that can't read Gradle
module metadata get the JVM JAR and POM. Gradle 6.0+ fails to resolve
those modules in a variant-aware way, always choosing the JVM artifacts.

To avoid issues on the consumer side when these dependencies are used,
we decided to drop support for Gradle < 6.0 in the MPP plugin.

Issue #KMM-233 Fixed
This commit is contained in:
Sergey Igushkin
2020-04-20 21:32:40 +03:00
committed by Sergey Igushkin
parent 89777f8bf3
commit e3d33cdc10
26 changed files with 170 additions and 291 deletions
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.gradle
import org.gradle.api.logging.LogLevel
import org.jetbrains.kotlin.gradle.util.*
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Assume
import org.junit.Test
import java.io.File
import kotlin.test.assertEquals
@@ -16,12 +17,15 @@ open class KotlinAndroid33GradleIT : KotlinAndroid32GradleIT() {
get() = GradleVersionRequired.AtLeast("5.0")
}
open class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT() {
open class KotlinAndroid36GradleIT : KotlinAndroid33GradleIT() {
override val androidGradlePluginVersion: AGPVersion
get() = AGPVersion.v3_2_0
get() = AGPVersion.v3_6_0
override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.AtLeast("6.0")
@Test
fun testAndroidWithNewMppApp() = with(Project("new-mpp-android", GradleVersionRequired.AtLeast("5.0"))) {
fun testAndroidWithNewMppApp() = with(Project("new-mpp-android", GradleVersionRequired.FOR_MPP_SUPPORT)) {
build("assemble", "compileDebugUnitTestJavaWithJavac", "printCompilerPluginOptions") {
assertSuccessful()
@@ -206,7 +210,7 @@ open class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT() {
}
@Test
fun testAndroidMppProductionDependenciesInTests() = with(Project("new-mpp-android", GradleVersionRequired.AtLeast("5.0"))) {
fun testAndroidMppProductionDependenciesInTests() = with(Project("new-mpp-android", GradleVersionRequired.FOR_MPP_SUPPORT)) {
// Test the fix for KT-29343
setupWorkingDir()
@@ -260,7 +264,7 @@ open class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT() {
}
@Test
fun testCustomAttributesInAndroidTargets() = with(Project("new-mpp-android", GradleVersionRequired.AtLeast("5.0"))) {
fun testCustomAttributesInAndroidTargets() = with(Project("new-mpp-android", GradleVersionRequired.FOR_MPP_SUPPORT)) {
// Test the fix for KT-27714
setupWorkingDir()
@@ -336,6 +340,11 @@ open class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT() {
assertTasksExecuted(lintTask) // Check that the lint task ran successfully, KT-27170
}
}
}
open class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT() {
override val androidGradlePluginVersion: AGPVersion
get() = AGPVersion.v3_2_0
@Test
fun testKaptUsingApOptionProvidersAsNestedInputOutput() = with(Project("AndroidProject")) {
@@ -444,6 +453,11 @@ class KotlinAndroid30GradleIT : KotlinAndroid3GradleIT() {
abstract class KotlinAndroid3GradleIT : AbstractKotlinAndroidGradleTests() {
@Test
fun testApplyWithFeaturePlugin() {
Assume.assumeTrue(
"The com.android.feature plugin has been deprecated and removed in newer versions",
androidGradlePluginVersion < AGPVersion.v3_6_0
)
val project = Project("AndroidProject")
project.setupWorkingDir()
@@ -666,6 +680,11 @@ fun getSomething() = 10
@Test
fun testAndroidExtensionsIncremental() {
Assume.assumeTrue(
"Ignored for newer AGP versions because of KT-38622",
androidGradlePluginVersion < AGPVersion.v3_6_0
)
val project = Project("AndroidExtensionsProject")
val options = defaultBuildOptions().copy(incremental = true)
@@ -751,6 +770,10 @@ fun getSomething() = 10
fun testMultiplatformAndroidCompile() = with(Project("multiplatformAndroidProject")) {
setupWorkingDir()
if (androidGradlePluginVersion >= AGPVersion.v3_6_0) {
}
// Check that the common module is not added to the deprecated configuration 'compile' (KT-23719):
gradleBuildScript("libAndroid").appendText(
"""${'\n'}
@@ -16,6 +16,9 @@ import kotlin.test.fail
class CocoaPodsIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.FOR_MPP_SUPPORT
// We use Kotlin DSL. Earlier Gradle versions fail at accessors codegen.
val gradleVersion = GradleVersionRequired.None
@@ -11,6 +11,9 @@ import org.junit.Test
class CommonNativeIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.FOR_MPP_SUPPORT
private fun doCommonNativeTest(
projectName: String,
libTargets: List<String>,
@@ -15,6 +15,9 @@ import kotlin.test.assertTrue
class FatFrameworkIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.FOR_MPP_SUPPORT
@Test
fun smokeIos() {
Assume.assumeTrue(HostManager.hostIsMac)
@@ -10,6 +10,9 @@ import org.junit.Test
class GeneralNativeIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.FOR_MPP_SUPPORT
@Test
fun testParallelExecutionDetection(): Unit = with(transformProjectWithPluginsDsl("native-parallel")) {
val compileTasks = arrayOf(":one:compileKotlinLinux", ":two:compileKotlinLinux")
@@ -22,6 +22,8 @@ import org.junit.Assume
sealed class GradleVersionRequired(val minVersion: String, val maxVersion: String?) {
companion object {
const val OLDEST_SUPPORTED = "4.9"
val FOR_MPP_SUPPORT = AtLeast("6.0")
}
class Exact(version: String) : GradleVersionRequired(version, version)
@@ -21,8 +21,11 @@ import kotlin.test.assertEquals
import kotlin.test.assertTrue
class HierarchicalMppIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired
get() = gradleVersion
companion object {
private val gradleVersion = GradleVersionRequired.AtLeast("5.0")
private val gradleVersion = GradleVersionRequired.FOR_MPP_SUPPORT
}
@Test
@@ -397,12 +400,7 @@ class HierarchicalMppIT : BaseGradleIT() {
}
@Test
fun testCompileOnlyDependencyProcessingForMetadataCompilations() = with(
Project(
"hierarchical-mpp-project-dependency",
GradleVersionRequired.AtLeast("5.0") // Bug in Gradle versions < 5.0: Gradle can't pick build dependencies from nested provider
)
) {
fun testCompileOnlyDependencyProcessingForMetadataCompilations() = with(Project("hierarchical-mpp-project-dependency")) {
publishThirdPartyLib(withGranularMetadata = true)
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
@@ -790,7 +790,7 @@ class KotlinGradleIT : BaseGradleIT() {
val projects = listOf(
Project("simpleProject"),
Project("kotlin2JsNoOutputFileProject"),
Project("sample-app", directoryPrefix = "new-mpp-lib-and-app")
Project("sample-app", GradleVersionRequired.FOR_MPP_SUPPORT, "new-mpp-lib-and-app")
)
projects.forEach {
@@ -820,7 +820,7 @@ class KotlinGradleIT : BaseGradleIT() {
}
@Test
fun testKt29971() = with(Project("kt-29971", GradleVersionRequired.AtLeast("5.0"))) {
fun testKt29971() = with(Project("kt-29971", GradleVersionRequired.FOR_MPP_SUPPORT)) {
build("jvm-app:build") {
assertSuccessful()
assertTasksExecuted(":jvm-app:compileKotlin")
@@ -828,7 +828,7 @@ class KotlinGradleIT : BaseGradleIT() {
}
@Test
fun testDetectingDifferentClassLoaders() = with(Project("kt-27059-pom-rewriting", GradleVersionRequired.AtLeast("4.10.2"))) {
fun testDetectingDifferentClassLoaders() = with(Project("kt-27059-pom-rewriting", GradleVersionRequired.FOR_MPP_SUPPORT)) {
setupWorkingDir()
val originalRootBuildScript = gradleBuildScript().readText()
@@ -1006,7 +1006,7 @@ class KotlinGradleIT : BaseGradleIT() {
}
@Test
fun testKtKt35942InternalsFromMainInTestViaTransitiveDeps() = with(Project("kt-35942-jvm")) {
fun testKtKt35942InternalsFromMainInTestViaTransitiveDeps() = with(Project("kt-35942-jvm", GradleVersionRequired.FOR_MPP_SUPPORT)) {
build(":lib1:compileTestKotlin") {
assertSuccessful()
assertTasksExecuted(":lib1:compileKotlin", ":lib2:jar")
@@ -1014,7 +1014,9 @@ class KotlinGradleIT : BaseGradleIT() {
}
@Test
fun testKtKt35942InternalsFromMainInTestViaTransitiveDepsAndroid() = with(Project("kt-35942-android")) {
fun testKtKt35942InternalsFromMainInTestViaTransitiveDepsAndroid() = with(
Project("kt-35942-android", GradleVersionRequired.FOR_MPP_SUPPORT)
) {
build(
":lib1:compileDebugUnitTestKotlin",
options = defaultBuildOptions().copy(
@@ -16,6 +16,9 @@ import org.junit.Test
class NativePlatformLibsIT : BaseGradleIT() {
override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.FOR_MPP_SUPPORT
private val oldCompilerVersion = "1.3.61"
private val currentCompilerVersion = NativeCompilerDownloader.DEFAULT_KONAN_VERSION
@@ -59,7 +59,7 @@ fun configure(): NativeTargets {
}
class NewMultiplatformIT : BaseGradleIT() {
val gradleVersion = GradleVersionRequired.None
val gradleVersion = GradleVersionRequired.FOR_MPP_SUPPORT
val nativeHostTargetName = configure().current
val supportedNativeTargets = configure().supported
@@ -438,7 +438,7 @@ class NewMultiplatformIT : BaseGradleIT() {
@Test
fun testMavenPublishAppliedBeforeMultiplatformPlugin() =
with(Project("sample-lib", GradleVersionRequired.AtLeast("5.0"), "new-mpp-lib-and-app")) {
with(Project("sample-lib", directoryPrefix = "new-mpp-lib-and-app")) {
setupWorkingDir()
gradleBuildScript().modify { "apply plugin: 'maven-publish'\n$it" }
@@ -449,7 +449,7 @@ class NewMultiplatformIT : BaseGradleIT() {
}
@Test
fun testResourceProcessing() = with(Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")) {
fun testResourceProcessing() = with(Project("sample-lib", directoryPrefix = "new-mpp-lib-and-app")) {
val targetsWithResources = listOf("jvm6", "nodeJs", "wasm32", nativeHostTargetName)
val processResourcesTasks =
targetsWithResources.map { ":${it}ProcessResources" }
@@ -465,6 +465,9 @@ class NewMultiplatformIT : BaseGradleIT() {
}
}
override val defaultGradleVersion: GradleVersionRequired
get() = gradleVersion
@Test
fun testSourceSetCyclicDependencyDetection() = with(Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")) {
setupWorkingDir()
@@ -492,7 +495,7 @@ class NewMultiplatformIT : BaseGradleIT() {
fun testJavaSupportInJvmTargets() = doTestJvmWithJava(testJavaSupportInJvmTargets = true)
private fun doTestJvmWithJava(testJavaSupportInJvmTargets: Boolean) =
with(Project("sample-lib", GradleVersionRequired.AtLeast("5.0"), "new-mpp-lib-and-app")) {
with(Project("sample-lib", directoryPrefix = "new-mpp-lib-and-app")) {
embedProject(Project("sample-lib-gradle-kotlin-dsl", directoryPrefix = "new-mpp-lib-and-app"))
lateinit var classesWithoutJava: Set<String>
@@ -941,35 +944,6 @@ class NewMultiplatformIT : BaseGradleIT() {
}
}
@Test
fun testPublishWithoutGradleMetadata() {
val libProject = Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")
with(libProject) {
setupWorkingDir()
projectDir.resolve("settings.gradle").modify { it.replace("enableFeaturePreview", "// enableFeaturePreview") }
build("publish") {
assertSuccessful()
val groupRepoDir = "repo/com/example"
// No root publication:
assertNoSuchFile("$groupRepoDir/sample-lib")
// Check that the platform publications have the metadata dependency
listOf("jvm6", "nodejs", "wasm32", nativeHostTargetName.toLowerCase()).forEach { targetAppendix ->
val targetPomPath = "$groupRepoDir/sample-lib-$targetAppendix/1.0/sample-lib-$targetAppendix-1.0.pom"
assertFileContains(
targetPomPath,
"<groupId>com.example</groupId>",
"<artifactId>sample-lib-metadata</artifactId>",
"<version>1.0</version>"
)
}
}
}
}
@Test
fun testEndorsedLibsController() {
with(
@@ -989,39 +963,6 @@ class NewMultiplatformIT : BaseGradleIT() {
}
}
@Test
fun testDependenciesOnMppLibraryPartsWithNoMetadata() {
val repoDir = with(Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")) {
setupWorkingDir()
projectDir.resolve("settings.gradle").modify { it.replace("enableFeaturePreview", "// enableFeaturePreview") }
build("publish") { assertSuccessful() }
projectDir.resolve("repo")
}
val dependencies = buildString {
append("dependencies {\n")
append(" allJvmImplementation 'com.example:sample-lib-jvm6:1.0'\n")
append(" nodeJsMainImplementation 'com.example:sample-lib-nodejs:1.0'\n")
for (target in supportedNativeTargets) {
append(" ${target}MainImplementation 'com.example:sample-lib-$target:1.0'\n")
}
append("}")
}
with(Project("sample-app", gradleVersion, "new-mpp-lib-and-app")) {
setupWorkingDir()
gradleBuildScript().modify {
it.replace("implementation 'com.example:sample-lib:1.0'", "implementation 'com.example:sample-lib-metadata:1.0'") +
"\nrepositories { maven { url '${repoDir.toURI()}' } }\n\n" + dependencies
}
build("assemble") {
assertSuccessful()
assertTasksExecuted(listOf("Jvm6", "NodeJs", "Wasm32", nativeHostTargetName.capitalize()).map { ":compileKotlin$it" })
}
}
}
@Test
fun testPublishingOnlySupportedNativeTargets() = with(Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")) {
val publishedVariant = nativeHostTargetName
@@ -1862,7 +1803,7 @@ class NewMultiplatformIT : BaseGradleIT() {
// Gradle 5.0 introduced a new API for Ivy repository layouts.
// MPP plugin uses this API to download K/N if Gradle version is >= 5.0.
// Check this too (see KT-30258).
with(Project("new-mpp-native-libraries", GradleVersionRequired.AtLeast("5.0"))) {
with(Project("new-mpp-native-libraries")) {
build("tasks", "-Pkotlin.native.version=1.3.50-eap-11606") {
assertSuccessful()
assertTrue(output.contains("Kotlin/Native distribution: "))
@@ -1872,31 +1813,24 @@ class NewMultiplatformIT : BaseGradleIT() {
}
@Test
fun testPublishMultimoduleProjectWithNoMetadata() = doTestPublishMultimoduleProject(withMetadata = false)
@Test
fun testPublishMultimoduleProjectWithMetadata() = doTestPublishMultimoduleProject(withMetadata = true)
private fun doTestPublishMultimoduleProject(withMetadata: Boolean) {
fun testPublishMultimoduleProjectWithMetadata() {
val libProject = Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")
libProject.setupWorkingDir()
val externalLibProject = Project("sample-external-lib", gradleVersion, "new-mpp-lib-and-app").apply {
if (withMetadata) {
setupWorkingDir()
// Publish it into local repository of adjacent lib:
gradleBuildScript().appendText(
"\n" + """
publishing {
repositories {
maven { url "file://${'$'}{rootProject.projectDir.absolutePath.replace('\\', '/')}/../sample-lib/repo" }
}
Project("sample-external-lib", gradleVersion, "new-mpp-lib-and-app").apply {
setupWorkingDir()
// Publish it into local repository of adjacent lib:
gradleBuildScript().appendText(
"\n" + """
publishing {
repositories {
maven { url "file://${'$'}{rootProject.projectDir.absolutePath.replace('\\', '/')}/../sample-lib/repo" }
}
""".trimIndent()
)
build("publish") {
assertSuccessful()
}
""".trimIndent()
)
build("publish") {
assertSuccessful()
}
}
@@ -1920,20 +1854,19 @@ class NewMultiplatformIT : BaseGradleIT() {
}
""".trimIndent()
}
if (withMetadata) {
gradleSettingsScript().appendText("\nenableFeaturePreview(\"GRADLE_METADATA\")")
// Add a dependency that is resolved with metadata:
gradleBuildScript("sample-app").appendText(
"\n" + """
repositories {
maven { url "file://${'$'}{rootProject.projectDir.absolutePath.replace('\\', '/')}/repo" }
}
dependencies {
commonMainApi 'com.external.dependency:external:1.2.3'
}
""".trimIndent()
)
}
gradleSettingsScript().appendText("\nenableFeaturePreview(\"GRADLE_METADATA\")")
// Add a dependency that is resolved with metadata:
gradleBuildScript("sample-app").appendText(
"\n" + """
repositories {
maven { url "file://${'$'}{rootProject.projectDir.absolutePath.replace('\\', '/')}/repo" }
}
dependencies {
commonMainApi 'com.external.dependency:external:1.2.3'
}
""".trimIndent()
)
gradleBuildScript().appendText(
"\n" + """
@@ -1949,20 +1882,18 @@ class NewMultiplatformIT : BaseGradleIT() {
""".trimIndent()
)
if (withMetadata) {
gradleBuildScript().appendText(
"\n" + """
publishing {
publications {
kotlinMultiplatform {
// KT-29485
artifactId = 'sample-lib-multiplatform'
}
gradleBuildScript().appendText(
"\n" + """
publishing {
publications {
kotlinMultiplatform {
// KT-29485
artifactId = 'sample-lib-multiplatform'
}
}
""".trimIndent()
)
}
}
""".trimIndent()
)
build("clean", "publish") {
assertSuccessful()
@@ -1978,20 +1909,18 @@ class NewMultiplatformIT : BaseGradleIT() {
"<artifactId>bar</artifactId>",
"<version>42</version>"
)
if (withMetadata) {
assertFileContains(
"repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.pom",
"<groupId>com.external.dependency</groupId>",
"<artifactId>external-jvm6</artifactId>",
"<version>1.2.3</version>"
)
assertFileContains(
"repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.pom",
"<groupId>com.external.dependency</groupId>",
"<artifactId>external-jvm6</artifactId>",
"<version>1.2.3</version>"
)
// Check that, despite the rewritten POM, the module metadata contains the original dependency:
val moduleMetadata = projectDir.resolve("repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.module").readText()
.replace("\\s+".toRegex(), "").replace("\n", "")
assertTrue { "\"group\":\"com.example\",\"module\":\"sample-lib-multiplatform\"" in moduleMetadata }
assertTrue { "\"group\":\"com.external.dependency\",\"module\":\"external\"" in moduleMetadata }
}
// Check that, despite the rewritten POM, the module metadata contains the original dependency:
val moduleMetadata = projectDir.resolve("repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.module").readText()
.replace("\\s+".toRegex(), "").replace("\n", "")
assertTrue { "\"group\":\"com.example\",\"module\":\"sample-lib-multiplatform\"" in moduleMetadata }
assertTrue { "\"group\":\"com.external.dependency\",\"module\":\"external\"" in moduleMetadata }
}
// Check that a user can disable rewriting of MPP dependencies in the POMs:
@@ -2000,31 +1929,21 @@ class NewMultiplatformIT : BaseGradleIT() {
assertFileContains(
"repo/com/exampleapp/sample-app-nodejs/1.0/sample-app-nodejs-1.0.pom",
"<groupId>com.example</groupId>",
if (withMetadata)
"<artifactId>sample-lib-multiplatform</artifactId>"
else
"<artifactId>sample-lib</artifactId>"
,
"<artifactId>sample-lib-multiplatform</artifactId>",
"<version>1.0</version>"
)
assertFileContains(
"repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.pom",
"<groupId>com.example</groupId>",
if (withMetadata)
"<artifactId>sample-lib-multiplatform</artifactId>"
else
"<artifactId>sample-lib</artifactId>"
,
"<artifactId>sample-lib-multiplatform</artifactId>",
"<version>1.0</version>"
)
if (withMetadata) {
assertFileContains(
"repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.pom",
"<groupId>com.external.dependency</groupId>",
"<artifactId>external</artifactId>",
"<version>1.2.3</version>"
)
}
assertFileContains(
"repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.pom",
"<groupId>com.external.dependency</groupId>",
"<artifactId>external</artifactId>",
"<version>1.2.3</version>"
)
}
}
}
@@ -2204,7 +2123,7 @@ class NewMultiplatformIT : BaseGradleIT() {
}
@Test
fun testDependenciesDsl() = with(transformProjectWithPluginsDsl("newMppDependenciesDsl", GradleVersionRequired.AtLeast("5.0"))) {
fun testDependenciesDsl() = with(transformProjectWithPluginsDsl("newMppDependenciesDsl")) {
val originalBuildscriptContent = gradleBuildScript("app").readText()
fun testDependencies() = testResolveAllConfigurations("app") {
@@ -2288,7 +2207,7 @@ class NewMultiplatformIT : BaseGradleIT() {
@Test
fun testKt29725() {
with(Project("new-mpp-native-libraries", GradleVersionRequired.Exact("5.2"))) {
with(Project("new-mpp-native-libraries")) {
// Assert that a project with a native target can be configured with Gradle 5.2
build("tasks") {
assertSuccessful()
@@ -2335,7 +2254,7 @@ class NewMultiplatformIT : BaseGradleIT() {
}
@Test
fun testPomRewritingInSinglePlatformProject() = with(Project("kt-27059-pom-rewriting", GradleVersionRequired.AtLeast("4.10.2"))) {
fun testPomRewritingInSinglePlatformProject() = with(Project("kt-27059-pom-rewriting")) {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
@@ -2411,22 +2330,6 @@ class NewMultiplatformIT : BaseGradleIT() {
doTestPomRewriting(mppProjectDependency = false, legacyPublishing = true, keepPomIntact = true)
}
@Test
fun testSuggestionToEnableMetadata() = with(Project("sample-lib", directoryPrefix = "new-mpp-lib-and-app")) {
build {
assertNotContains(GRADLE_NO_METADATA_WARNING)
gradleSettingsScript().modify { it.replace("enableFeaturePreview(", "//") }
build {
if (testGradleVersionAtLeast("5.3-rc-2")) {
assertContains(GRADLE_NO_METADATA_WARNING)
} else {
assertNotContains(GRADLE_NO_METADATA_WARNING)
}
}
}
}
@Test
fun testIgnoreDisabledNativeTargets() = with(Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")) {
build {
@@ -2445,7 +2348,7 @@ class NewMultiplatformIT : BaseGradleIT() {
}
private fun testAssociateCompilationsImpl() {
with(Project("new-mpp-associate-compilations", GradleVersionRequired.AtLeast("5.0"))) {
with(Project("new-mpp-associate-compilations")) {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
@@ -2485,7 +2388,7 @@ class NewMultiplatformIT : BaseGradleIT() {
}
@Test
fun testTestRunsApi() = with(Project("new-mpp-associate-compilations", GradleVersionRequired.AtLeast("5.0"))) {
fun testTestRunsApi() = with(Project("new-mpp-associate-compilations")) {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.gradle.util.*
import org.junit.Test
class VariantAwareDependenciesIT : BaseGradleIT() {
private val gradleVersion = GradleVersionRequired.None
private val gradleVersion = GradleVersionRequired.FOR_MPP_SUPPORT
@Test
fun testJvmKtAppResolvesMppLib() {
@@ -89,19 +89,17 @@ class VariantAwareDependenciesIT : BaseGradleIT() {
.replace("\"org.jetbrains.kotlin:kotlin-stdlib\"", "\"org.jetbrains.kotlin:kotlin-stdlib:\$kotlin_version\"")
}
if (testGradleVersionAtLeast("5.3-rc-1")) {
gradleBuildScript().appendText(
// In Gradle 5.3, the variants of a Kotlin MPP can't be disambiguated in a pure Java project's deprecated
// configurations that don't have a proper 'org.gradle.usage' attribute value, see KT-30378
"\n" + """
configurations {
configure([compile, runtime, testCompile, testRuntime, getByName('default')]) {
canBeResolved = false
}
gradleBuildScript().appendText(
// In Gradle 5.3+, the variants of a Kotlin MPP can't be disambiguated in a pure Java project's deprecated
// configurations that don't have a proper 'org.gradle.usage' attribute value, see KT-30378
"\n" + """
configurations {
configure([compile, runtime, testCompile, testRuntime, getByName('default')]) {
canBeResolved = false
}
""".trimIndent()
)
}
}
""".trimIndent()
)
}
with(outerProject) {
@@ -134,6 +132,18 @@ class VariantAwareDependenciesIT : BaseGradleIT() {
embedProject(innerProject)
gradleBuildScript(innerProject.projectName).appendText("\ndependencies { compile rootProject }")
gradleBuildScript(innerProject.projectName).appendText(
// Newer Gradle versions fail to resolve the deprecated configurations because of variant-aware resolution ambiguity between
// the *Elements configuration and its sub-variants (classes, resources)
"\n" + """
configurations {
configure([compile, runtime, testCompile, testRuntime, getByName('default')]) {
canBeResolved = false
}
}
""".trimIndent()
)
testResolveAllConfigurations(innerProject.projectName)
}
}
@@ -260,7 +270,7 @@ class VariantAwareDependenciesIT : BaseGradleIT() {
@Test
fun testJvmWithJavaProjectCanBeResolvedInAllConfigurations() =
with(Project("new-mpp-jvm-with-java-multi-module")) {
with(Project("new-mpp-jvm-with-java-multi-module", GradleVersionRequired.FOR_MPP_SUPPORT)) {
testResolveAllConfigurations("app")
}
@@ -45,7 +45,7 @@ class WorkersIT : BaseGradleIT() {
isParallel: Boolean,
jsCompilerType: KotlinJsCompilerType
) =
with(Project("new-mpp-parallel")) {
with(Project("new-mpp-parallel", GradleVersionRequired.FOR_MPP_SUPPORT)) {
val options = defaultBuildOptions().copy(
parallelTasksInProject = isParallel,
withDaemon = false,
@@ -22,6 +22,7 @@ class AGPVersion private constructor(private val versionNumber: VersionNumber) {
val v3_1_0 = fromString("3.1.0")
val v3_2_0 = fromString("3.2.0")
val v3_3_2 = fromString("3.3.2")
val v3_6_0 = fromString("3.6.0")
val v4_0_ALPHA_8 = fromString("4.0.0-alpha08")
}
}
@@ -4,10 +4,6 @@
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:label="@string/app_name"
@@ -4,10 +4,6 @@
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:label="@string/app_name"
@@ -3,8 +3,6 @@
package="platform.kotlin.android.test"
>
<uses-sdk android:minSdkVersion="19" />
<application/>
</manifest>
@@ -13,8 +13,11 @@ repositories {
}
kotlin {
val jvm6 = jvm("jvm6")
val jvm6 = jvm("jvm6") {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 6)
}
val jvm8 = jvm("jvm8") {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
compilations["main"].kotlinOptions.jvmTarget = "1.8"
}
val nodeJs = js("nodeJs")
@@ -47,8 +47,12 @@ kotlin {
}
targets {
fromPreset(presets.jvm, 'jvm6')
fromPreset(presets.jvm, 'jvm6') {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 6)
}
fromPreset(presets.jvm, 'jvm8') {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8)
compilations.main {
tasks.getByName(compileKotlinTaskName) {
kotlinOptions {
@@ -30,9 +30,6 @@ open class KotlinMultiplatformExtension :
val testableTargets: NamedDomainObjectCollection<KotlinTargetWithTests<*, *>>
get() = targets.withType(KotlinTargetWithTests::class.java)
internal var isGradleMetadataAvailable: Boolean = false
internal var isGradleMetadataExperimental: Boolean = false
fun metadata(configure: KotlinOnlyTarget<AbstractKotlinCompilation<*>>.() -> Unit = { }): KotlinOnlyTarget<AbstractKotlinCompilation<*>> =
@Suppress("UNCHECKED_CAST")
(targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME) as KotlinOnlyTarget<AbstractKotlinCompilation<*>>).also(configure)
@@ -32,7 +32,7 @@ open class KotlinMetadataTarget @Inject constructor(project: Project) :
val usageContexts = mutableSetOf<DefaultKotlinUsageContext>()
// This usage value is only needed for Maven scope mapping. Don't replace it with a custom Kotlin Usage value
val javaApiUsage = project.usageByName(if (isGradleVersionAtLeast(5, 3)) "java-api-jars" else JAVA_API)
val javaApiUsage = project.usageByName("java-api-jars")
usageContexts += run {
val allMetadataJar = project.tasks.getByName(KotlinMetadataTargetConfigurator.ALL_METADATA_JAR_NAME)
@@ -21,6 +21,7 @@ import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.jvm.tasks.Jar
import org.gradle.util.ConfigureUtil
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.configureOrCreate
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
@@ -56,7 +57,7 @@ class KotlinMultiplatformPlugin(
}
override fun apply(project: Project) {
checkGradleCompatibility()
checkGradleCompatibility("the Kotlin Multiplatform plugin", GradleVersion.version("6.0"))
project.plugins.apply(JavaBasePlugin::class.java)
SingleWarningPerBuild.show(project, "Kotlin Multiplatform Projects are an experimental feature.")
@@ -75,12 +76,6 @@ class KotlinMultiplatformPlugin(
addExtension("presets", presets)
defaultJsCompilerType = PropertiesProvider(project).jsCompiler
isGradleMetadataAvailable =
featurePreviews.activeFeatures.find { it.name == "GRADLE_METADATA" }?.let { metadataFeature ->
isGradleMetadataExperimental = true
featurePreviews.isFeatureEnabled(metadataFeature)
} ?: true // the feature entry will be gone once the feature is stable
}
setupDefaultPresets(project)
@@ -180,12 +175,6 @@ class KotlinMultiplatformPlugin(
private fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") { _ ->
if (isGradleVersionAtLeast(5, 3) &&
project.multiplatformExtension.run { isGradleMetadataExperimental && !isGradleMetadataAvailable }
) {
SingleWarningPerBuild.show(project, GRADLE_NO_METADATA_WARNING)
}
val targets = project.multiplatformExtension.targets
val kotlinSoftwareComponent = project.multiplatformExtension.rootSoftwareComponent
@@ -198,13 +187,6 @@ class KotlinMultiplatformPlugin(
kotlinSoftwareComponent.publicationDelegate = this@apply
}
// Publish the root publication only if Gradle metadata publishing is enabled:
project.tasks.withType(AbstractPublishToMaven::class.java).configureEach { publishTask ->
publishTask.onlyIf {
publishTask.publication != rootPublication || project.multiplatformExtension.isGradleMetadataAvailable
}
}
// Enforce the order of creating the publications, since the metadata publication is used in the other publications:
(targets.getByName(METADATA_TARGET_NAME) as AbstractKotlinTarget).createMavenPublications(publishing.publications)
targets
@@ -302,17 +284,6 @@ class KotlinMultiplatformPlugin(
internal fun sourceSetFreeCompilerArgsPropertyName(sourceSetName: String) =
"kotlin.mpp.freeCompilerArgsForSourceSet.$sourceSetName"
internal const val GRADLE_NO_METADATA_WARNING = "This build consumes Gradle module metadata but does not produce " +
"it when publishing Kotlin multiplatform libraries. \n" +
"To enable Gradle module metadata in publications, add 'enableFeaturePreview(\"GRADLE_METADATA\")' " +
"to the settings.gradle file. \n" +
"See: https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#experimental-metadata-publishing-mode"
internal const val GRADLE_OLD_METADATA_WARNING = "This build is set up to publish a Kotlin multiplatform library " +
"with an outdated Gradle module metadata format, which newer Gradle versions won't be able to consume. \n" +
"Please update the Gradle version to 5.3 or newer. \n" +
"See: https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#experimental-metadata-publishing-mode"
}
}
@@ -170,14 +170,7 @@ abstract class AbstractKotlinTarget(
val metadataTarget =
kotlinExtension.targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME) as AbstractKotlinTarget
if (kotlinExtension.isGradleMetadataAvailable) {
KotlinVariantWithMetadataVariant(compilation, usageContexts, metadataTarget)
} else {
// we should only add the Kotlin metadata dependency if we publish no Gradle metadata related to Kotlin MPP;
// with metadata, such a dependency would get invalid, since a platform module should only depend on modules for that
// same platform, not Kotlin metadata modules
KotlinVariantWithMetadataDependency(compilation, usageContexts, metadataTarget)
}
KotlinVariantWithMetadataVariant(compilation, usageContexts, metadataTarget)
}
result.componentName = componentName
@@ -97,38 +97,6 @@ class KotlinVariantWithMetadataVariant(
override fun getVariants() = metadataTarget.components
}
class KotlinVariantWithMetadataDependency(
producingCompilation: KotlinCompilation<*>,
val originalUsages: Set<DefaultKotlinUsageContext>,
private val metadataTarget: AbstractKotlinTarget
) : KotlinVariantWithCoordinates(producingCompilation, originalUsages) {
override fun getUsages(): Set<KotlinUsageContext> = originalUsages.mapTo(mutableSetOf()) { usageContext ->
KotlinUsageContextWithAdditionalDependencies(usageContext, setOf(metadataDependency()))
}
private fun metadataDependency(): ModuleDependency {
val metadataComponent = metadataTarget.kotlinComponents.single() as KotlinTargetComponentWithPublication
val project = metadataTarget.project
// The metadata component may not be published, e.g. if the whole project is not published:
val metadataPublication: MavenPublication? = metadataComponent.publicationDelegate
val metadataGroupId = metadataPublication?.groupId ?: project.group
val metadataArtifactId = metadataPublication?.artifactId ?: metadataComponent.defaultArtifactId
val metadataVersion = metadataPublication?.version ?: project.version
return target.project.dependencies.module("$metadataGroupId:$metadataArtifactId:$metadataVersion") as ModuleDependency
}
class KotlinUsageContextWithAdditionalDependencies(
val parentUsageContext: DefaultKotlinUsageContext,
val additionalDependencies: Set<ModuleDependency>
) : KotlinUsageContext by parentUsageContext {
override fun getDependencies() = parentUsageContext.dependencies + additionalDependencies
override fun getGlobalExcludes(): Set<ExcludeRule> = emptySet()
}
}
class JointAndroidKotlinTargetComponent(
override val target: KotlinAndroidTarget,
private val nestedVariants: Set<KotlinVariant>,
@@ -196,7 +196,6 @@ private fun associateDependenciesWithActualModuleDependencies(
private fun KotlinTargetComponent.findUsageContext(configurationName: String): UsageContext? {
val usageContexts = when (this) {
is KotlinVariantWithMetadataDependency -> originalUsages
is SoftwareComponentInternal -> usages
else -> emptySet()
}
@@ -51,12 +51,15 @@ internal fun TaskInputs.dirCompatible(dirPath: Any) {
inputsDirMethod(this, dirPath)
}
internal fun checkGradleCompatibility(minSupportedVersion: GradleVersion = GradleVersion.version("4.9")) {
internal fun checkGradleCompatibility(
withComponent: String = "the Kotlin Gradle plugin",
minSupportedVersion: GradleVersion = GradleVersion.version("4.9")
) {
val currentVersion = GradleVersion.current()
if (currentVersion < minSupportedVersion) {
throw GradleException(
"Current version of Gradle $currentVersion is not compatible with Kotlin plugin. " +
"Please use Gradle $minSupportedVersion or newer or previous version of Kotlin plugin."
"The current Gradle version ${currentVersion.version} is not compatible with $withComponent. " +
"Please use Gradle ${minSupportedVersion.version} or newer, or the previous version of the Kotlin plugin."
)
}
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.gradle.internals
import org.jetbrains.kotlin.gradle.plugin.KOTLIN_12X_MPP_DEPRECATION_WARNING
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin.Companion.GRADLE_NO_METADATA_WARNING
import org.jetbrains.kotlin.gradle.targets.native.internal.NO_NATIVE_STDLIB_PROPERTY_WARNING
import org.jetbrains.kotlin.gradle.targets.native.internal.NO_NATIVE_STDLIB_WARNING
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinProjectStructureMetadata
@@ -19,8 +18,6 @@ fun parseKotlinSourceSetMetadataFromXml(document: Document): KotlinProjectStruct
const val MULTIPLATFORM_PROJECT_METADATA_FILE_NAME = MULTIPLATFORM_PROJECT_METADATA_FILE_NAME
const val GRADLE_NO_METADATA_WARNING = GRADLE_NO_METADATA_WARNING
const val DISABLED_NATIVE_TARGETS_REPORTER_DISABLE_WARNING_PROPERTY_NAME = DisabledNativeTargetsReporter.DISABLE_WARNING_PROPERTY_NAME
const val DISABLED_NATIVE_TARGETS_REPORTER_WARNING_PREFIX: String = DisabledNativeTargetsReporter.WARNING_PREFIX