diff --git a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts index afd9bf912ea..f2becb99393 100644 --- a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts @@ -53,7 +53,7 @@ dependencies { compile("com.google.code.gson:gson:${rootProject.extra["versions.jar.gson"]}") compile("de.undercouch:gradle-download-task:4.0.2") implementation("com.github.gundy:semver4j:0.16.4") - + compileOnly("com.android.tools.build:gradle:2.0.0") compileOnly("com.android.tools.build:gradle-core:2.0.0") compileOnly("com.android.tools.build:builder:2.0.0") @@ -79,8 +79,9 @@ dependencies { compileOnly("com.android.tools.build:gradle:3.0.0") { isTransitive = false } compileOnly("com.android.tools.build:gradle-core:3.0.0") { isTransitive = false } compileOnly("com.android.tools.build:builder-model:3.0.0") { isTransitive = false } + testImplementation("com.android.tools.build:gradle:4.0.1") - testCompile(intellijDep()) { includeJars( "junit", "serviceMessages", rootProject = rootProject) } + testCompile(intellijDep()) { includeJars("junit", "serviceMessages", rootProject = rootProject) } testCompileOnly(project(":compiler")) testCompile(projectTests(":kotlin-build-common")) @@ -103,7 +104,7 @@ runtimeJar(rewriteDefaultJarDepsToShadedCompiler()).configure { from { jarContents.asFileTree.map { - if (it.endsWith(".jar")) zipTree(it) + if (it.endsWith(".jar")) zipTree(it) else it } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 03b769e218a..22b1474eba5 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -774,6 +774,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool val kotlinSourceSet = project.kotlinExtension.sourceSets.maybeCreate( kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget, sourceSet.name) ).apply { + createDefaultDependsOnEdges(kotlinAndroidTarget, sourceSet, this) kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin"))) kotlin.srcDirs(sourceSet.java.srcDirs) } @@ -845,6 +846,21 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool } } + private fun createDefaultDependsOnEdges( + kotlinAndroidTarget: KotlinAndroidTarget, + androidSourceSet: AndroidSourceSet, + kotlinSourceSet: KotlinSourceSet + ) { + val commonSourceSetName = when (androidSourceSet.name) { + "main" -> "commonMain" + "test" -> "commonTest" + "androidTest" -> "commonTest" + else -> return + } + val commonSourceSet = kotlinAndroidTarget.project.kotlinExtension.sourceSets.findByName(commonSourceSetName) ?: return + kotlinSourceSet.dependsOn(commonSourceSet) + } + /** * The Android variants have their configurations extendsFrom relation set up in a way that only some of the configurations of the * variants propagate the dependencies from production variants to test ones. To make this dependency propagation work for the Kotlin @@ -961,14 +977,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool // Register the source only after the task is created, because the task is required for that: compilation.source(defaultSourceSet) - - // In MPPs, add the common main Kotlin sources to non-test variants, the common test sources to test variants - val commonSourceSetName = if (getTestedVariantData(variantData) == null) - KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME else - KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME - project.kotlinExtension.sourceSets.findByName(commonSourceSetName)?.let { - compilation.source(it) - } } private fun postprocessVariant( diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidDependsOnEdgesTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidDependsOnEdgesTest.kt new file mode 100644 index 00000000000..0eaa81ac20b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidDependsOnEdgesTest.kt @@ -0,0 +1,108 @@ +/* + * 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.android + +import com.android.build.gradle.LibraryExtension +import org.gradle.api.internal.project.ProjectInternal +import org.gradle.testfixtures.ProjectBuilder +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import kotlin.test.Test +import kotlin.test.assertEquals + +class KotlinAndroidDependsOnEdgesTest { + @Test + fun `default android source set declares dependsOn commonMain`() { + val project = ProjectBuilder.builder().build() + project.plugins.apply("kotlin-multiplatform") + project.plugins.apply("android-library") + + /* Arbitrary minimal Android setup */ + val android = project.extensions.getByName("android") as LibraryExtension + android.compileSdkVersion(30) + + /* Minimal MPP setup */ + val kotlin = project.kotlinExtension as KotlinMultiplatformExtension + kotlin.android("android") + + /* Force evaluation */ + project as ProjectInternal + project.evaluate() + + val commonMain = kotlin.sourceSets.getByName("commonMain") + val commonTest = kotlin.sourceSets.getByName("commonTest") + val androidMain = kotlin.sourceSets.getByName("androidMain") + val androidTest = kotlin.sourceSets.getByName("androidTest") + val androidAndroidTest = kotlin.sourceSets.getByName("androidAndroidTest") + + assertEquals( + setOf(commonMain), androidMain.dependsOn, + "Expected androidMain to dependOn commonMain" + ) + + assertEquals( + setOf(commonTest), androidTest.dependsOn, + "Expected androidTest to dependOn commonTest" + ) + + assertEquals( + setOf(commonTest), androidAndroidTest.dependsOn, + "Expected androidAndroidTest to dependOn commonTest" + ) + } + + @Test + fun `custom dependsOn edges`() { + val project = ProjectBuilder.builder().build() + project.plugins.apply("kotlin-multiplatform") + project.plugins.apply("android-library") + + /* Arbitrary minimal Android setup */ + val android = project.extensions.getByName("android") as LibraryExtension + android.compileSdkVersion(30) + + /* Custom MPP setup */ + val kotlin = project.kotlinExtension as KotlinMultiplatformExtension + kotlin.android("android") + kotlin.sourceSets.apply { + val jvmMain = create("jvmMain") { + it.dependsOn(getByName("commonMain")) + } + getByName("androidMain") { + it.dependsOn(jvmMain) + } + } + + /* Force evaluation */ + project as ProjectInternal + project.evaluate() + + val commonMain = kotlin.sourceSets.getByName("commonMain") + val commonTest = kotlin.sourceSets.getByName("commonTest") + val jvmMain = kotlin.sourceSets.getByName("jvmMain") + val androidMain = kotlin.sourceSets.getByName("androidMain") + val androidTest = kotlin.sourceSets.getByName("androidTest") + val androidAndroidTest = kotlin.sourceSets.getByName("androidAndroidTest") + + assertEquals( + setOf(commonMain, jvmMain).sorted(), androidMain.dependsOn.sorted(), + "Expected androidMain to depend on commonMain and jvmMain" + ) + + assertEquals( + setOf(commonTest), androidTest.dependsOn, + "Expected androidTest to only depend on commonTest" + ) + + assertEquals( + setOf(commonTest), androidAndroidTest.dependsOn, + "Expected androidAndroidTest to only depend on commonTest" + ) + } +} + +private fun Iterable.sorted() = this.sortedBy { it.name }