From b51461b5c5be4bd54a9edd2fff3be9e3ca42f46e Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Tue, 30 Oct 2018 06:29:22 +0300 Subject: [PATCH] Drop support for Gradle 3.x #KT-27885 Fixed --- .../gradle/plugin/KotlinPlatformType.kt | 9 +- .../AbstractKotlinAndroidGradleTests.kt | 23 +- .../jetbrains/kotlin/gradle/BaseGradleIT.kt | 8 +- .../kotlin/gradle/GradleVersionRequired.kt | 5 +- .../org/jetbrains/kotlin/gradle/Kapt3IT.kt | 22 -- .../kotlin/gradle/Kotlin2JsGradlePluginIT.kt | 8 +- .../kotlin/gradle/KotlinGradlePluginIT.kt | 137 +---------- .../kotlin/gradle/MultiplatformGradleIT.kt | 4 +- .../org/jetbrains/kotlin/gradle/UpToDateIT.kt | 7 +- .../kotlin/gradle/model/AllOpenModelIT.kt | 4 - .../kotlin/gradle/model/KaptModelIT.kt | 5 - .../kotlin/gradle/model/NoArgModelIT.kt | 3 - .../gradle/model/SamWithReceiverModelIT.kt | 4 - .../gradle/dsl/KotlinProjectExtension.kt | 8 +- .../kapt/Kapt3KotlinGradleSubplugin.kt | 5 +- .../plugin/CopyClassesToJavaOutputStatus.kt | 54 ----- .../kotlin/gradle/plugin/KotlinPlugin.kt | 92 ++------ .../gradle/plugin/KotlinPluginWrapper.kt | 3 + .../gradle/plugin/KotlinTargetConfigurator.kt | 12 +- .../LegacyAndroidAndroidProjectHandler.kt | 7 - .../plugin/ProjectLocalConfigurations.kt | 23 +- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 3 + .../kotlin/gradle/plugin/mpp/KotlinUsages.kt | 8 +- .../plugin/mpp/kotlinCompilationOutputs.kt | 8 +- .../tasks/InspectClassesForMultiModuleIC.kt | 11 +- .../kotlin/gradle/tasks/SyncOutputTask.kt | 216 ------------------ .../kotlin/gradle/utils/compatibiltiy.kt | 12 + 27 files changed, 71 insertions(+), 630 deletions(-) delete mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/CopyClassesToJavaOutputStatus.kt delete mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt index c6c4071fab0..553b12056f0 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt @@ -47,14 +47,9 @@ enum class KotlinPlatformType: Named, Serializable { fun setupAttributesMatchingStrategy(attributesSchema: AttributesSchema) { attributesSchema.attribute(KotlinPlatformType.attribute).run { - if (isGradleAtLeast(4, 0)) { - compatibilityRules.add(CompatibilityRule::class.java) - disambiguationRules.add(DisambiguationRule::class.java) - } + compatibilityRules.add(CompatibilityRule::class.java) + disambiguationRules.add(DisambiguationRule::class.java) } } } } - -private fun isGradleAtLeast(major: Int, minor: Int) = - GradleVersion.current() >= GradleVersion.version("$major.$minor") \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt index 945c540e059..d2ffec05493 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt @@ -14,7 +14,7 @@ import kotlin.test.assertTrue class KotlinAndroidGradleIT : AbstractKotlinAndroidGradleTests(androidGradlePluginVersion = "2.3.0") { override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.InRange("3.4", "4.10.2") + get() = GradleVersionRequired.InRange("4.0", "4.10.2") } // TODO If we there is a way to fetch the latest Android plugin version, test against the latest version @@ -329,17 +329,6 @@ abstract class AbstractKotlinAndroidGradleTests(val androidGradlePluginVersion: // Execute 'assembleAndroidTest' first, without 'build' side effects project.build("assembleAndroidTest") { assertSuccessful() - if (project.testGradleVersionBelow("4.0")) { - val tasks = ArrayList().apply { - for (subProject in listOf("Android", "Lib")) { - for (flavor in listOf("Flavor1", "Flavor2")) { - add(":$subProject:copy${flavor}DebugKotlinClasses") - } - } - } - // with the new AGP we don't need copy classes tasks - assertTasksExecuted(tasks) - } } } @@ -590,12 +579,10 @@ fun getSomething() = 10 ":libAndroid:compileReleaseUnitTestKotlin" ) - val kotlinFolder = if (project.testGradleVersionAtLeast("4.0")) "kotlin" else "" - - assertFileExists("lib/build/classes/$kotlinFolder/main/foo/PlatformClass.kotlin_metadata") - assertFileExists("lib/build/classes/$kotlinFolder/test/foo/PlatformTest.kotlin_metadata") - assertFileExists("libJvm/build/classes/$kotlinFolder/main/foo/PlatformClass.class") - assertFileExists("libJvm/build/classes/$kotlinFolder/test/foo/PlatformTest.class") + assertFileExists("lib/build/classes/kotlin/main/foo/PlatformClass.kotlin_metadata") + assertFileExists("lib/build/classes/kotlin/test/foo/PlatformTest.kotlin_metadata") + assertFileExists("libJvm/build/classes/kotlin/main/foo/PlatformClass.class") + assertFileExists("libJvm/build/classes/kotlin/test/foo/PlatformTest.class") assertFileExists("libAndroid/build/tmp/kotlin-classes/debug/foo/PlatformClass.class") assertFileExists("libAndroid/build/tmp/kotlin-classes/release/foo/PlatformClass.class") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index e656c431d92..bae19e686a8 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -511,14 +511,10 @@ abstract class BaseGradleIT { assertSameFiles(sources, compiledJavaSources.projectRelativePaths(this.project), "Compiled Java files differ:\n ") fun Project.resourcesDir(subproject: String? = null, sourceSet: String = "main"): String = - (subproject?.plus("/") ?: "") + "build/" + - (if (testGradleVersionBelow("4.0")) "classes/" else "resources/") + - sourceSet + "/" + (subproject?.plus("/") ?: "") + "build/resources/$sourceSet/" fun Project.classesDir(subproject: String? = null, sourceSet: String = "main", language: String = "kotlin"): String = - (subproject?.plus("/") ?: "") + "build/classes/" + - (if (testGradleVersionAtLeast("4.0")) "$language/" else "") + - sourceSet + "/" + (subproject?.plus("/") ?: "") + "build/classes/$language/$sourceSet/" fun Project.testGradleVersionAtLeast(version: String): Boolean = GradleVersion.version(chooseWrapperVersionOrFinishTest()) >= GradleVersion.version(version) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/GradleVersionRequired.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/GradleVersionRequired.kt index 26d479a8a8c..7c5661add25 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/GradleVersionRequired.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/GradleVersionRequired.kt @@ -21,10 +21,7 @@ import org.junit.Assume sealed class GradleVersionRequired(val minVersion: String, val maxVersion: String?) { companion object { - //TODO once the plugin is compiled with API level 1.0, replace with the really supported one (3.2) - // Currently, it will lead to failing tests due to the conflict with the pre-release kotlin-reflect - // bundled into Gradle 3.2...3.4 - const val OLDEST_SUPPORTED = "3.5" + const val OLDEST_SUPPORTED = "4.0" } class Exact(version: String) : GradleVersionRequired(version, version) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt index 2bdbcd9762f..20bdba6757d 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt @@ -308,28 +308,6 @@ open class Kapt3IT : Kapt3BaseIT() { } } - @Test - fun testKaptClassesDirSync() { - val project = Project("autoService", GradleVersionRequired.Exact("3.5"), directoryPrefix = "kapt2") - - project.build("build") { - assertSuccessful() - assertKaptSuccessful() - assertFileExists("processor/build/classes/main/META-INF/services/javax.annotation.processing.Processor") - assertFileExists("processor/build/classes/main/processor/MyProcessor.class") - } - - project.projectDir.getFileByName("MyProcessor.kt").modify { - it.replace("@AutoService(Processor::class)", "") - } - - project.build(":processor:build") { - assertSuccessful() - assertNoSuchFile("processor/build/classes/main/META-INF/services/javax.annotation.processing.Processor") - assertFileExists("processor/build/classes/main/processor/MyProcessor.class") - } - } - /** * Tests that compile arguments are properly copied from compileKotlin to kaptTask */ diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt index 30049d557d9..a58cae1b781 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt @@ -133,7 +133,7 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { @Test fun testCompilerTestAccessInternalProduction() { - val project = Project("kotlin2JsInternalTest", GradleVersionRequired.Exact("3.5")) + val project = Project("kotlin2JsInternalTest") project.build("runRhino") { assertSuccessful() @@ -167,7 +167,7 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { @Test fun testKotlinJsBuiltins() { - val project = Project("kotlinBuiltins", GradleVersionRequired.AtLeast("4.0")) + val project = Project("kotlinBuiltins") project.setupWorkingDir() val buildGradle = File(project.projectDir, "app").getFileByName("build.gradle") @@ -309,7 +309,7 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { /** Issue: KT-18495 */ @Test fun testNoSeparateClassesDirWarning() { - val project = Project("kotlin2JsProject", GradleVersionRequired.AtLeast("4.0")) + val project = Project("kotlin2JsProject") project.build("build") { assertSuccessful() assertNotContains("this build assumes a single directory for all classes from a source set") @@ -317,7 +317,7 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { } @Test - fun testIncrementalCompilation() = Project("kotlin2JsICProject", GradleVersionRequired.AtLeast("4.0")).run { + fun testIncrementalCompilation() = Project("kotlin2JsICProject").run { build("build") { assertSuccessful() assertContains(USING_JS_INCREMENTAL_COMPILATION_MESSAGE) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt index 472d43facf4..cfb8915d3d4 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.gradle import org.gradle.api.logging.LogLevel -import org.jetbrains.kotlin.gradle.plugin.CopyClassesToJavaOutputStatus import org.jetbrains.kotlin.gradle.tasks.USING_JVM_INCREMENTAL_COMPILATION_MESSAGE import org.jetbrains.kotlin.gradle.util.* import org.junit.Test @@ -259,24 +258,6 @@ class KotlinGradleIT : BaseGradleIT() { } } - @Test - fun testWipeClassesDirectoryBetweenBuilds() { - val project = Project("kotlinJavaProject", GradleVersionRequired.Exact("3.5")) - - project.build("build") { - assertSuccessful() - } - - val javaOutputDir = File(project.projectDir, "build/classes") - assert(javaOutputDir.isDirectory) { "Classes directory does not exist $javaOutputDir" } - javaOutputDir.deleteRecursively() - - project.build("build") { - assertSuccessful() - assertTasksUpToDate(":compileKotlin") - } - } - @Test fun testMoveClassToOtherModule() { val project = Project("moveClassToOtherModule") @@ -317,7 +298,7 @@ class KotlinGradleIT : BaseGradleIT() { @Test fun testKotlinBuiltins() { - val project = Project("kotlinBuiltins", GradleVersionRequired.AtLeast("4.0")) + val project = Project("kotlinBuiltins") project.build("build") { assertSuccessful() @@ -361,42 +342,6 @@ class KotlinGradleIT : BaseGradleIT() { } } - @Test - fun testChangeDestinationDir() { - val project = Project("kotlinProject", GradleVersionRequired.Exact("3.5")) - project.setupWorkingDir() - - val fileToRemove = File(project.projectDir, "src/main/kotlin/removeMe.kt") - fileToRemove.writeText("val x = 1") - val classFilePath = "build/classes/main/RemoveMeKt.class" - - project.build("build") { - assertSuccessful() - assertFileExists(classFilePath) - } - - // Check that after the change the build succeeds and no stale classes remain in the java classes dir - File(project.projectDir, "build.gradle").modify { - "$it\n\ncompileKotlin.destinationDir = file(\"\${project.buildDir}/compileKotlin\")" - } - fileToRemove.delete() - - project.build("build") { - assertSuccessful() - assertNoSuchFile(classFilePath) - // Check that the fallback to non-incremental copying was chosen - assertContains("Non-incremental copying files") - } - - // Check that the classes are copied incrementally under normal conditions - fileToRemove.writeText("val x = 1") - project.build("build") { - assertSuccessful() - assertFileExists(classFilePath) - assertNotContains("Non-incremental copying files") - } - } - @Test fun testDowngradeTo106() { val project = Project("kotlinProject") @@ -515,7 +460,7 @@ class KotlinGradleIT : BaseGradleIT() { @Test fun testSeparateOutputGradle40() { - val project = Project("kotlinJavaProject", GradleVersionRequired.AtLeast("4.0")) + val project = Project("kotlinJavaProject") project.build("compileDeployKotlin", "assemble") { assertSuccessful() @@ -529,10 +474,6 @@ class KotlinGradleIT : BaseGradleIT() { // Check that the Java output is intact: assertFileExists("build/classes/java/main/demo/Greeter.class") - - // Check that the sync output task is not used with Gradle 4.0+ and there's no old Kotlin output layout - assertNotContains(":copyMainKotlinClasses") - assertNoSuchFile("build/kotlin-classes") } } @@ -574,80 +515,6 @@ class KotlinGradleIT : BaseGradleIT() { } } - @Test - fun testDisableSeparateClassesDirs() { - - fun CompiledProject.check( - copyClassesToJavaOutput: Boolean?, - expectBuildCacheWarning: Boolean, - expectGradleLowVersionWarning: Boolean - ) { - - val separateDirPath = kotlinClassesDir() + "demo/KotlinGreetingJoiner.class" - val singleDirPath = javaClassesDir() + "demo/KotlinGreetingJoiner.class" - - assertSuccessful() - when (copyClassesToJavaOutput) { - true -> { - assertNoSuchFile(separateDirPath) - assertFileExists(singleDirPath) - } - false -> { - assertFileExists(separateDirPath) - assertNoSuchFile(singleDirPath) - } - } - - if (expectBuildCacheWarning) - assertContains(CopyClassesToJavaOutputStatus.buildCacheWarningMessage) - else - assertNotContains(CopyClassesToJavaOutputStatus.buildCacheWarningMessage) - - if (expectGradleLowVersionWarning) - assertContains(CopyClassesToJavaOutputStatus.gradleVersionTooLowWarningMessage) - else - assertNotContains(CopyClassesToJavaOutputStatus.gradleVersionTooLowWarningMessage) - } - - Project("simpleProject", GradleVersionRequired.Exact("4.0")).apply { - build("build") { - check( - copyClassesToJavaOutput = false, - expectBuildCacheWarning = false, - expectGradleLowVersionWarning = false - ) - } - File(projectDir, "build.gradle").appendText("\nkotlin.copyClassesToJavaOutput = true") - build("clean", "build") { - check( - copyClassesToJavaOutput = true, - expectBuildCacheWarning = false, - expectGradleLowVersionWarning = false - ) - } - build("clean", "build", options = defaultBuildOptions().copy(withBuildCache = true)) { - check( - copyClassesToJavaOutput = true, - expectBuildCacheWarning = true, - expectGradleLowVersionWarning = false - ) - } - projectDir.deleteRecursively() - } - - Project("simpleProject", GradleVersionRequired.Exact("3.4")).apply { - setupWorkingDir() - File(projectDir, "build.gradle").appendText("\nkotlin.copyClassesToJavaOutput = true") - build("build") { - check( - copyClassesToJavaOutput = null, - expectBuildCacheWarning = false, - expectGradleLowVersionWarning = true - ) - } - } - } - @Test fun testSrcDirTaskDependency() { Project("simpleProject", GradleVersionRequired.AtLeast("4.1")).apply { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt index 285e8b8a9e6..dd0d55fef9b 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MultiplatformGradleIT.kt @@ -29,7 +29,7 @@ class MultiplatformGradleIT : BaseGradleIT() { @Test fun testMultiplatformCompile() { - val project = Project("multiplatformProject", GradleVersionRequired.AtLeast("4.0")) + val project = Project("multiplatformProject") project.build("build") { assertSuccessful() @@ -89,7 +89,7 @@ class MultiplatformGradleIT : BaseGradleIT() { @Test fun testSubprojectWithAnotherClassLoader() { - with(Project("multiplatformProject", GradleVersionRequired.AtLeast("4.0"))) { + with(Project("multiplatformProject")) { setupWorkingDir() // Make sure there is a plugin applied with the plugins DSL, so that Gradle loads the diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/UpToDateIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/UpToDateIT.kt index 84ae086b5ec..84f7d429946 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/UpToDateIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/UpToDateIT.kt @@ -137,12 +137,7 @@ class UpToDateIT : BaseGradleIT() { lateinit var helloWorldKtClass: File override fun mutateProject(project: Project) = with(project) { - val kotlinOutputPath = - if (testGradleVersionAtLeast("4.0")) - project.classesDir() - else - // Before 4.0, we should delete the classes from the temporary dir to make compileKotlin rerun: - "build/kotlin-classes/main/" + val kotlinOutputPath = project.classesDir() helloWorldKtClass = File(projectDir, kotlinOutputPath + "demo/KotlinGreetingJoiner.class") Assume.assumeTrue(helloWorldKtClass.exists()) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/AllOpenModelIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/AllOpenModelIT.kt index 6a62b927871..a609064acf7 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/AllOpenModelIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/AllOpenModelIT.kt @@ -6,16 +6,12 @@ package org.jetbrains.kotlin.gradle.model import org.jetbrains.kotlin.gradle.BaseGradleIT -import org.jetbrains.kotlin.gradle.GradleVersionRequired import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertNull import kotlin.test.assertTrue class AllOpenModelIT : BaseGradleIT() { - override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.AtLeast("4.0") - @Test fun testAllOpenSimple() { val project = Project("allOpenSimple") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/KaptModelIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/KaptModelIT.kt index 0fb6e922f5c..de59a3fd3f9 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/KaptModelIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/KaptModelIT.kt @@ -6,16 +6,11 @@ package org.jetbrains.kotlin.gradle.model import org.jetbrains.kotlin.gradle.BaseGradleIT -import org.jetbrains.kotlin.gradle.GradleVersionRequired import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertNull -import kotlin.test.assertTrue class KaptModelIT : BaseGradleIT() { - override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.AtLeast("4.0") - @Test fun testKaptSimple() { val project = Project("simple", directoryPrefix = "kapt2") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/NoArgModelIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/NoArgModelIT.kt index c353a0af10a..ad44c98b464 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/NoArgModelIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/NoArgModelIT.kt @@ -14,9 +14,6 @@ import kotlin.test.assertNull import kotlin.test.assertTrue class NoArgModelIT : BaseGradleIT() { - override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.AtLeast("4.0") - @Test fun testNoArgKt18668() { val project = Project("noArgKt18668") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/SamWithReceiverModelIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/SamWithReceiverModelIT.kt index 6010b0437fc..0c6abcdf98c 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/SamWithReceiverModelIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/model/SamWithReceiverModelIT.kt @@ -6,16 +6,12 @@ package org.jetbrains.kotlin.gradle.model import org.jetbrains.kotlin.gradle.BaseGradleIT -import org.jetbrains.kotlin.gradle.GradleVersionRequired import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertNull import kotlin.test.assertTrue class SamWithReceiverModelIT : BaseGradleIT() { - override val defaultGradleVersion: GradleVersionRequired - get() = GradleVersionRequired.AtLeast("4.0") - @Test fun testSamWithReceiverSimple() { val project = Project("samWithReceiverSimple") 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 a7e2df35872..70cdae3241c 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 @@ -51,13 +51,7 @@ open class KotlinSingleJavaTargetExtension : KotlinProjectExtension() { internal lateinit var target: KotlinWithJavaTarget<*> } -open class KotlinJvmProjectExtension : KotlinSingleJavaTargetExtension() { - /** - * With Gradle 4.0+, disables the separate output directory for Kotlin, falling back to sharing the deprecated - * single classes directory per source set. With Gradle < 4.0, has no effect. - * */ - var copyClassesToJavaOutput = false -} +open class KotlinJvmProjectExtension : KotlinSingleJavaTargetExtension() open class ExperimentalExtension { var coroutines: Coroutines? = null diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index d0dde695b9b..99a46affa7d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -379,9 +379,8 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { kotlinCompilation?.run { output.apply { - if (tryAddClassesDir { project.files(classesOutputDir).builtBy(kaptTask) }) { - kotlinCompile.attachClassesDir { classesOutputDir } - } + addClassesDir { project.files(classesOutputDir).builtBy(kaptTask) } + kotlinCompile.attachClassesDir { classesOutputDir } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/CopyClassesToJavaOutputStatus.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/CopyClassesToJavaOutputStatus.kt deleted file mode 100644 index 6f5b5f0aa27..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/CopyClassesToJavaOutputStatus.kt +++ /dev/null @@ -1,54 +0,0 @@ -package org.jetbrains.kotlin.gradle.plugin - -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.specs.Spec -import org.gradle.api.tasks.compile.JavaCompile -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension -import org.jetbrains.kotlin.gradle.logging.kotlinWarn -import org.jetbrains.kotlin.gradle.utils.ParsedGradleVersion -import java.util.* - -object CopyClassesToJavaOutputStatus { - fun isEnabled(project: Project): Boolean { - val kotlinJvmExt = project.kotlinJvmExt ?: return false - if (kotlinJvmExt.copyClassesToJavaOutput) { - if (isGradleVersionTooLow(project)) { - if (warningReportedForProject.add(project)) { - project.logger.kotlinWarn(gradleVersionTooLowWarningMessage) - } - } else { - addCacheWarningToJavaTasks(project) - } - return true - } - return false - } - - private val warningReportedForProject = Collections.newSetFromMap(WeakHashMap()) - - private fun isGradleVersionTooLow(project: Project): Boolean { - return (ParsedGradleVersion.parse(project.gradle.gradleVersion) ?: return false) < ParsedGradleVersion(4, 0) - } - - private fun addCacheWarningToJavaTasks(project: Project) { - project.tasks.withType(JavaCompile::class.java).all { - val warningCacheIfSpec = Spec { - if (warningReportedForProject.add(project)) { - project.logger.kotlinWarn(buildCacheWarningMessage) - } - return@Spec true - } - it.outputs.javaClass.getMethod("cacheIf", Spec::class.java).invoke(it.outputs, warningCacheIfSpec) - } - } - - const val buildCacheWarningMessage = "The 'kotlin.copyClassesToJavaOutput' option should not be used with Gradle " + - "build cache" - - const val gradleVersionTooLowWarningMessage = "The 'kotlin.copyClassesToJavaOutput' option has no effect when " + - "used with Gradle < 4.0" - - private val Project.kotlinJvmExt: KotlinJvmProjectExtension? - get() = extensions.findByType(KotlinJvmProjectExtension::class.java) -} \ No newline at end of file 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 69913d487e5..1e2991e693f 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 @@ -59,29 +59,21 @@ internal abstract class KotlinSourceSetProcessor>( protected abstract fun doTargetSpecificProcessing() protected val logger = Logging.getLogger(this.javaClass)!! - protected val isSeparateClassesDirSupported: Boolean by lazy { - !CopyClassesToJavaOutputStatus.isEnabled(project) && isGradleVersionAtLeast(4, 0) - } - protected val sourceSetName: String = kotlinCompilation.compilationName protected val kotlinTask: TaskHolder = registerKotlinCompileTask() protected val javaSourceSet: SourceSet? = (kotlinCompilation as? KotlinWithJavaCompilation<*>)?.javaSourceSet - protected open val defaultKotlinDestinationDir: File + private val defaultKotlinDestinationDir: File get() { - return if (isSeparateClassesDirSupported) { - val kotlinExt = project.kotlinExtension - val targetSubDirectory = - if (kotlinExt is KotlinSingleJavaTargetExtension) - "" // In single-target projects, don't add the target name part to this path - else - kotlinCompilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty() - File(project.buildDir, "classes/kotlin/$targetSubDirectory${kotlinCompilation.compilationName}") - } else { - kotlinCompilation.output.classesDirs.singleFile - } + val kotlinExt = project.kotlinExtension + val targetSubDirectory = + if (kotlinExt is KotlinSingleJavaTargetExtension) + "" // In single-target projects, don't add the target name part to this path + else + kotlinCompilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty() + return File(project.buildDir, "classes/kotlin/$targetSubDirectory${kotlinCompilation.compilationName}") } private fun registerKotlinCompileTask(): TaskHolder { @@ -91,7 +83,7 @@ internal abstract class KotlinSourceSetProcessor>( it.description = taskDescription it.mapClasspath { kotlinCompilation.compileDependencyFiles } it.setDestinationDir { defaultKotlinDestinationDir } - kotlinCompilation.output.tryAddClassesDir { project.files(kotlinTask.doGetTask().destinationDir).builtBy(kotlinTask.doGetTask()) } + kotlinCompilation.output.addClassesDir { project.files(kotlinTask.doGetTask().destinationDir).builtBy(kotlinTask.doGetTask()) } } return kotlinCompile } @@ -171,11 +163,6 @@ internal class Kotlin2JvmSourceSetProcessor( ) : KotlinSourceSetProcessor( project, tasksProvider, "Compiles the $kotlinCompilation.", kotlinCompilation ) { - override val defaultKotlinDestinationDir: File - get() = if (!isSeparateClassesDirSupported) - File(project.buildDir, "kotlin-classes/$sourceSetName") else - super.defaultKotlinDestinationDir - override fun doRegisterTask(project: Project, taskName: String, configureAction: (KotlinCompile)->(Unit)): TaskHolder = tasksProvider.registerKotlinJVMTask(project, taskName, kotlinCompilation, configureAction) @@ -201,19 +188,8 @@ internal class Kotlin2JvmSourceSetProcessor( javaTask?.let { configureJavaTask(kotlinTaskInstance, it, logger) } - var syncOutputTask: SyncOutputTask? = null - - if (!isSeparateClassesDirSupported && javaTask != null) { - syncOutputTask = registerSyncOutputTask(project, kotlinTaskInstance, javaTask, sourceSetName) - } - if (project.pluginManager.hasPlugin("java-library") && sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) { - val (classesProviderTask, classesDirectory) = when { - isSeparateClassesDirSupported -> kotlinTaskInstance.let { it to it.destinationDir } - else -> syncOutputTask!!.let { it to it.javaOutputDir } - } - - registerKotlinOutputForJavaLibrary(classesDirectory, classesProviderTask) + registerKotlinOutputForJavaLibrary(kotlinTaskInstance.destinationDir, kotlinTaskInstance) } } } @@ -249,15 +225,9 @@ internal class Kotlin2JvmSourceSetProcessor( } } -internal fun KotlinCompilationOutput.tryAddClassesDir( - classesDirProvider: () -> FileCollection -): Boolean = - if (isGradleVersionAtLeast(4, 0)) { - classesDirs.from(Callable { classesDirProvider() }) - true - } else { - false - } +internal fun KotlinCompilationOutput.addClassesDir(classesDirProvider: () -> FileCollection) { + classesDirs.from(Callable { classesDirProvider() }) +} internal class Kotlin2JsSourceSetProcessor( project: Project, @@ -305,10 +275,6 @@ internal class Kotlin2JsSourceSetProcessor( kotlinTaskInstance.destinationDir = outputDir - if (!isSeparateClassesDirSupported && kotlinCompilation is KotlinWithJavaCompilation<*>) { - kotlinCompilation.javaSourceSet.output.setClassesDirCompatible(kotlinTaskInstance.destinationDir) - } - appliedPlugins .flatMap { it.getSubpluginKotlinTasks(project, kotlinTaskInstance) } .forEach { task -> kotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> task.source(sourceSet.kotlin) } } @@ -621,6 +587,8 @@ internal open class KotlinAndroidPlugin( ) : Plugin { override fun apply(project: Project) { + checkGradleCompatibility() + val androidTarget = KotlinAndroidTarget("", project) applyToTarget(kotlinPluginVersion, androidTarget) registry.register(KotlinModelBuilder(kotlinPluginVersion, androidTarget)) @@ -873,38 +841,10 @@ internal fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractComp * ex. it adds some support libraries jars after execution of prepareComAndroidSupportSupportV42311Library task, * so it's only safe to modify javaTask.classpath right before its usage */ + // todo: remove? javaTask.appendClasspathDynamically(kotlinTask.destinationDir!!) } -internal fun syncOutputTaskName(variantName: String) = "copy${variantName.capitalize()}KotlinClasses" - -internal fun registerSyncOutputTask( - project: Project, - kotlinCompile: KotlinCompile, - javaTask: AbstractCompile, - variantName: String -): SyncOutputTask { - val kotlinDir = kotlinCompile.destinationDir - val javaDir = javaTask.destinationDir - val taskName = syncOutputTaskName(variantName) - - // registerTask(project: Project, name: String, type: Class, disableLazy: Boolean, body: (T)->(Unit)) : TaskHolder { - val syncTask = registerTask(project, taskName, SyncOutputTask::class.java) { - it.kotlinOutputDir = kotlinDir - it.javaOutputDir = javaDir - it.kotlinTask = kotlinCompile - it.kaptClassesDir = getKaptGeneratedClassesDir(project, variantName) - // copying should be executed after a latter task - javaTask.finalizedByIfNotFailed(it) - } - - kotlinCompile.javaOutputDir = javaDir - - project.logger.kotlinDebug { "Created task ${syncTask.doGetTask().path} to copy kotlin classes from $kotlinDir to $javaDir" } - - return syncTask.doGetTask() -} - private fun ifKaptEnabled(project: Project, block: () -> Unit) { var triggered = false diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index 82cbd36038a..7eb5ec846fb 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory import org.jetbrains.kotlin.gradle.tasks.KOTLIN_COMPILER_EMBEDDABLE import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP +import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility import java.io.FileNotFoundException import java.util.* import javax.inject.Inject @@ -49,6 +50,8 @@ abstract class KotlinBasePluginWrapper( DefaultKotlinSourceSetFactory(project, fileResolver) override fun apply(project: Project) { + checkGradleCompatibility() + project.configurations.maybeCreate(COMPILER_CLASSPATH_CONFIGURATION_NAME).defaultDependencies { it.add(project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_COMPILER_EMBEDDABLE:$kotlinPluginVersion")) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index 3ba6c280ff4..34092b35ab6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -35,7 +35,6 @@ import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile import org.jetbrains.kotlin.gradle.tasks.CInteropProcess import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink -import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import java.io.File import java.util.* @@ -517,7 +516,7 @@ open class KotlinNativeTargetConfigurator( destinationDir = klibOutputDirectory(compilation) addCompilerPlugins() - compilation.output.tryAddClassesDir { + compilation.output.addClassesDir { project.files(this.outputFile).builtBy(this) } } @@ -777,14 +776,7 @@ open class KotlinNativeTargetConfigurator( } internal fun Project.usageByName(usageName: String): Usage = - if (isGradleVersionAtLeast(4, 0)) { - // `project.objects` is an API introduced in Gradle 4.0 - project.objects.named(Usage::class.java, usageName) - } else { - val usagesClass = Class.forName("org.gradle.api.internal.attributes.Usages") - val usagesMethod = usagesClass.getMethod("usage", String::class.java) - usagesMethod(null, usageName) as Usage - } + project.objects.named(Usage::class.java, usageName) fun Configuration.usesPlatformOf(target: KotlinTarget): Configuration { attributes.attribute(KotlinPlatformType.attribute, target.platformType) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt index fa776ae5d8a..f260cbd0956 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt @@ -63,14 +63,7 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl javaTask.classpath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt)) } - getTestedVariantData(variantData)?.let { testedVariantData -> - // Android Gradle plugin bypasses the Gradle finalizedBy for its tasks in some cases, and - // the Kotlin classes may not be copied for the tested variant. Make sure they are. - kotlinTask.dependsOn(syncOutputTaskName(getVariantName(testedVariantData))) - } - configureJavaTask(kotlinTask, javaTask, logger) - registerSyncOutputTask(project, kotlinTask, javaTask, getVariantName(variantData)) // In lib modules, the androidTest variants get the classes jar in their classpath instead of the Java // destination dir. Attach the JAR to be consumed as friend path: diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/ProjectLocalConfigurations.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/ProjectLocalConfigurations.kt index 2b7f4f347e9..e9dd14ac006 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/ProjectLocalConfigurations.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/ProjectLocalConfigurations.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.plugin import org.gradle.api.artifacts.Configuration import org.gradle.api.attributes.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget -import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast object ProjectLocalConfigurations { val ATTRIBUTE: Attribute = Attribute.of("org.jetbrains.kotlin.localToProject", String::class.java) @@ -18,10 +17,8 @@ object ProjectLocalConfigurations { fun setupAttributesMatchingStrategy(attributesSchema: AttributesSchema) = with(attributesSchema) { attribute(ATTRIBUTE) { - if (gradleVersionSupportsAttributeRules) { - it.compatibilityRules.add(ProjectLocalCompatibility::class.java) - it.disambiguationRules.add(ProjectLocalDisambiguation::class.java) - } + it.compatibilityRules.add(ProjectLocalCompatibility::class.java) + it.disambiguationRules.add(ProjectLocalDisambiguation::class.java) } } @@ -41,23 +38,17 @@ object ProjectLocalConfigurations { } internal fun Configuration.setupAsLocalTargetSpecificConfigurationIfSupported(target: KotlinTarget) { - if (gradleVersionSupportsAttributeRules && - // don't setup in old MPP common modules, as their output configurations with KotlinPlatformType attribute would - // fail to resolve as transitive dependencies of the platform modules, just as we don't mark their - // `api/RuntimeElements` with the KotlinPlatformType - (target !is KotlinWithJavaTarget<*> || target.platformType != KotlinPlatformType.common) - ) { + // don't setup in old MPP common modules, as their output configurations with KotlinPlatformType attribute would + // fail to resolve as transitive dependencies of the platform modules, just as we don't mark their + // `api/RuntimeElements` with the KotlinPlatformType + if ((target !is KotlinWithJavaTarget<*> || target.platformType != KotlinPlatformType.common)) { usesPlatformOf(target) attributes.attribute(ProjectLocalConfigurations.ATTRIBUTE, ProjectLocalConfigurations.LOCAL_TO_PROJECT_PREFIX + target.project.path) } } internal fun Configuration.setupAsPublicConfigurationIfSupported(target: KotlinTarget) { - if (gradleVersionSupportsAttributeRules && - (target !is KotlinWithJavaTarget<*> || target.platformType != KotlinPlatformType.common) - ) { + if ((target !is KotlinWithJavaTarget<*> || target.platformType != KotlinPlatformType.common)) { attributes.attribute(ProjectLocalConfigurations.ATTRIBUTE, ProjectLocalConfigurations.PUBLIC_VALUE) } } - -internal val gradleVersionSupportsAttributeRules = isGradleVersionAtLeast(4, 0) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index b359e0bc8ce..7515b85a2de 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild +import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.presetName @@ -59,6 +60,8 @@ class KotlinMultiplatformPlugin( } override fun apply(project: Project) { + checkGradleCompatibility() + project.plugins.apply(JavaBasePlugin::class.java) SingleWarningPerBuild.show(project, "Kotlin Multiplatform Projects are an experimental feature.") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt index f807c969edf..988499e38a0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt @@ -97,11 +97,9 @@ object KotlinUsages { } internal fun setupAttributesMatchingStrategy(attributesSchema: AttributesSchema) { - if (isGradleVersionAtLeast(4, 0)) { - attributesSchema.attribute(Usage.USAGE_ATTRIBUTE) { strategy -> - strategy.compatibilityRules.add(KotlinJavaRuntimeJarsCompatibility::class.java) - strategy.disambiguationRules.add(KotlinUsagesDisambiguation::class.java) - } + attributesSchema.attribute(Usage.USAGE_ATTRIBUTE) { strategy -> + strategy.compatibilityRules.add(KotlinJavaRuntimeJarsCompatibility::class.java) + strategy.disambiguationRules.add(KotlinUsagesDisambiguation::class.java) } } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilationOutputs.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilationOutputs.kt index 04241372ad1..5da5891041c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilationOutputs.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilationOutputs.kt @@ -9,7 +9,6 @@ import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationOutput -import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import java.io.File import java.util.concurrent.Callable @@ -48,12 +47,7 @@ class KotlinWithJavaCompilationOutput( } override val classesDirs: ConfigurableFileCollection = - if (isGradleVersionAtLeast(4, 0)) - javaSourceSetOutput.classesDirs as ConfigurableFileCollection - else - // In Gradle < 4.0 `SourceSetOutput` does not have `classesDirs` - @Suppress("DEPRECATION") - compilation.target.project.files(Callable { javaSourceSetOutput.classesDir }) + javaSourceSetOutput.classesDirs as ConfigurableFileCollection override val allOutputs: FileCollection get() = javaSourceSetOutput diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/InspectClassesForMultiModuleIC.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/InspectClassesForMultiModuleIC.kt index 81394696542..168cfeb9ee8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/InspectClassesForMultiModuleIC.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/InspectClassesForMultiModuleIC.kt @@ -10,8 +10,6 @@ import org.gradle.api.file.FileCollection import org.gradle.api.plugins.JavaPluginConvention import org.gradle.api.tasks.* import org.gradle.jvm.tasks.Jar -import org.jetbrains.kotlin.gradle.utils.isClassFile -import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import java.io.File internal open class InspectClassesForMultiModuleIC : DefaultTask() { @@ -33,13 +31,8 @@ internal open class InspectClassesForMultiModuleIC : DefaultTask() { val convention = project.convention.findPlugin(JavaPluginConvention::class.java) val sourceSet = convention?.sourceSets?.findByName(sourceSetName) ?: return project.files() - return if (isGradleVersionAtLeast(4, 0)) { - val fileTrees = sourceSet.output.classesDirs.map { project.fileTree(it).include("**/*.class") } - project.files(fileTrees) - } else { - sourceSet.output.asFileTree.filter { it.isClassFile() } - } - + val fileTrees = sourceSet.output.classesDirs.map { project.fileTree(it).include("**/*.class") } + return project.files(fileTrees) } @get:Input diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt deleted file mode 100644 index 8686410cb78..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.gradle.tasks - -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.* -import org.gradle.api.tasks.incremental.IncrementalTaskInputs -import org.gradle.api.tasks.incremental.InputFileDetails -import org.jetbrains.kotlin.gradle.logging.kotlinDebug -import org.jetbrains.kotlin.gradle.utils.isParentOf -import java.io.File -import java.io.ObjectInputStream -import java.io.ObjectOutputStream -import java.util.* -import kotlin.properties.Delegates - -/** - * Copies kotlin classes to java output directory. - * No other way to get our classes into apk for android until API is provided https://code.google.com/p/android/issues/detail?id=200714 - * - * Utilises gradle for tracking input/output changes. - * 0. Gradle takes snapshots of annotated properties after compilation. - * 1. kotlinOutputDir as input files. These files will be copied. - * Copying will be done incrementally unless output classes are wiped out - * (by IncrementalJavaCompilationSafeguard task from android gradle plugin for example). - * 2. kotlinClassesInJavaOutputDir as output files -- copied classes in java output dir. - * When they are changed or removed gradle tells us that incremental build is not possible (inputs.isIncremental is false). - * 3. We do non-incremental sync in the following way: - * a. previously copied files are deleted (to do so we save the list of copied files after copying); - * b. all kotlin files are copied to java output dir. - * - * It is possible that some file was converted from kotlin to java. - * In this case gradle will tell us to make non-incremental sync. - * To workaround this scenario we also save timestamp of copied class. - * On step (a) of sync process we do not delete the class in java output dir - * if it's timestamp now is newer than when we copied it - * (assuming it was modified by javac when class was converted to java). - */ -internal open class SyncOutputTask : DefaultTask() { - @get:InputFiles - var kotlinOutputDir: File by Delegates.notNull() - - @get:InputFiles - var kaptClassesDir: File by Delegates.notNull() - - // Marked as input to make Gradle fall back to non-incremental build when it changes. - @get:Input - protected val classesDirs: List - get() = listOf(kotlinOutputDir, kaptClassesDir).filter(File::exists) - - @get:OutputDirectory - var javaOutputDir: File by Delegates.notNull() - - @get:Internal - var kotlinTask: KotlinCompile by Delegates.notNull() - - // OutputDirectory needed for task to be incremental - @get:OutputDirectory - val workingDir: File by lazy { - File(kotlinTask.taskBuildDirectory, "sync") - } - - private val timestampsFile: File by lazy { - File(workingDir, TIMESTAMP_FILE_NAME) - } - - private val timestamps: MutableMap by lazy { - readTimestamps(timestampsFile, javaOutputDir) - } - - init { - outputs.upToDateWhen { - for ((file, ts) in timestamps) { - if (!file.exists()) { - logger.kotlinDebug { "$file does not exist" } - return@upToDateWhen false - } - - if (file.lastModified() != ts) { - logger.kotlinDebug { "$file ts is different" } - return@upToDateWhen false - } - } - - return@upToDateWhen true - } - } - - @Suppress("unused") - @TaskAction - fun execute(inputs: IncrementalTaskInputs): Unit { - val sourceDirs = classesDirs.joinToString() - if (inputs.isIncremental) { - logger.kotlinDebug { "Incremental copying files from $sourceDirs to $javaOutputDir" } - inputs.outOfDate { processIncrementally(it) } - inputs.removed { processIncrementally(it) } - } else { - logger.kotlinDebug { "Non-incremental copying files from $sourceDirs to $javaOutputDir" } - processNonIncrementally() - } - - saveTimestamps(timestampsFile, timestamps, javaOutputDir) - } - - private fun processNonIncrementally() { - for ((file, timestamp) in timestamps) { - // wipe all files written by us - // do not remove files converted to java (newer timestamp) - if (file.lastModified() == timestamp) { - file.delete() - } - } - - timestampsFile.delete() - timestamps.clear() - - for (dir in classesDirs) { - dir.walkTopDown().forEach { - copy(it, it.siblingInJavaDir(baseDir = dir)) - } - } - } - - private fun processIncrementally(input: InputFileDetails) { - val fileInKotlinDir = input.file - val fileInJavaDir = fileInKotlinDir.siblingInJavaDir() - - if (input.isRemoved) { - // file was removed in kotlin dir, remove from java as well - remove(fileInJavaDir) - } else { - // copy modified or added file from kotlin to java - copy(fileInKotlinDir, fileInJavaDir) - } - } - - private fun remove(fileInJavaDir: File) { - if (!fileInJavaDir.isFile) return - - fileInJavaDir.delete() - timestamps.remove(fileInJavaDir) - - logger.kotlinDebug { - "Removed kotlin class ${fileInJavaDir.relativeTo(javaOutputDir).path} from $javaOutputDir" - } - } - - private fun copy(fileInKotlinDir: File, fileInJavaDir: File) { - if (!fileInKotlinDir.isFile) return - - fileInJavaDir.parentFile.mkdirs() - fileInKotlinDir.copyTo(fileInJavaDir, overwrite = true) - - timestamps[fileInJavaDir] = fileInJavaDir.lastModified() - - logger.kotlinDebug { - "Copied kotlin class ${fileInKotlinDir.relativeTo(kotlinOutputDir).path} from $kotlinOutputDir to $javaOutputDir" - } - } - - private fun File.siblingInJavaDir(baseDir: File? = null): File { - val base = baseDir ?: classesDirs.find { it.isParentOf(this, strict = true) }!! - return File(javaOutputDir, this.relativeTo(base).path) - } -} - -private val TIMESTAMP_FILE_NAME = "kotlin-files-in-java-timestamps.bin" - -private fun readTimestamps(tsFile: File, filesBaseDir: File): MutableMap { - val result = HashMap() - if (!tsFile.isFile) return result - - ObjectInputStream(tsFile.inputStream()).use { input -> - val size = input.readInt() - - repeat(size) { - val path = input.readUTF() - val timestamp = input.readLong() - result[File(filesBaseDir, path)] = timestamp - } - } - - return result -} - -private fun saveTimestamps(snapshotFile: File, timestamps: Map, filesBaseDir: File) { - if (!snapshotFile.exists()) { - snapshotFile.parentFile.mkdirs() - snapshotFile.createNewFile() - } else { - snapshotFile.delete() - } - - ObjectOutputStream(snapshotFile.outputStream()).use { out -> - out.writeInt(timestamps.size) - - for ((file, timestamp) in timestamps) { - out.writeUTF(file.relativeTo(filesBaseDir).path) - out.writeLong(timestamp) - } - } -} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/compatibiltiy.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/compatibiltiy.kt index 7d704c25873..71beeabc7ba 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/compatibiltiy.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/compatibiltiy.kt @@ -16,10 +16,12 @@ package org.jetbrains.kotlin.gradle.utils +import org.gradle.api.GradleException import org.gradle.api.Task import org.gradle.api.tasks.SourceSetOutput import org.gradle.api.tasks.TaskInputs import org.gradle.api.tasks.TaskOutputs +import org.gradle.util.GradleVersion internal val Task.inputsCompatible: TaskInputs get() = inputs @@ -93,4 +95,14 @@ private val setClassesDirMethod by lazy { internal fun SourceSetOutput.setClassesDirCompatible(dirPath: Any) { setClassesDirMethod(this, dirPath) +} + +internal fun checkGradleCompatibility(minSupportedVersion: GradleVersion = GradleVersion.version("4.0")) { + 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." + ) + } } \ No newline at end of file