From fabf75f4e247d72d9ce2045a948fc333b3e3523b Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Wed, 31 Jan 2024 16:15:29 +0700 Subject: [PATCH] [Gradle] Pass Android-related sources to KotlinSourceSet instead task Setting sources through compile task is not compatible with Multiplatform K2 because for such sources no K2 Fragment relations will be set and compilation will fail. ^KT-63753 Verification Pending --- .../gradle/android/KotlinAndroidMppIT.kt | 54 +++++++++++++++++++ .../targets/android/AndroidProjectHandler.kt | 10 ++-- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/KotlinAndroidMppIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/KotlinAndroidMppIT.kt index 0c218282a70..423a8776d7e 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/KotlinAndroidMppIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/KotlinAndroidMppIT.kt @@ -961,4 +961,58 @@ class KotlinAndroidMppIT : KGPBaseTest() { } } + @DisplayName("KT-63753: K2 File \"does not belong to any module\" when it is generated by `registerJavaGeneratingTask` in AGP") + @GradleAndroidTest + fun sourceGenerationTaskAddedToAndroidVariant( + gradleVersion: GradleVersion, + agpVersion: String, + jdkVersion: JdkVersions.ProvidedJdk + ) { + project( + "new-mpp-android", gradleVersion, + defaultBuildOptions.copy(androidVersion = agpVersion), + buildJdk = jdkVersion.location + ) { + // Hacks for TODO: KT-65426 + val appPath = subProject("app").projectPath + appPath.resolve("src/main/java/app/example/com/app_sample").deleteRecursively() + appPath.resolve("src/commonMain/kotlin/A.kt").replaceText("expect fun f(): Unit", "") + + // Code copied from the reproducer from KT-63753 + subProject("app").buildGradleKts.appendText( + """ + + abstract class FileGeneratingTask : DefaultTask() { + @get:OutputDirectory + abstract val outputDir: DirectoryProperty + + @TaskAction + fun taskAction() { + val outputDirFile = outputDir.asFile.get() + outputDirFile.mkdirs() + val file = File(outputDirFile, "Test.kt") + val text = ""${'"'} + val hello = "World!" + ""${'"'} + file.writeText(text) + } + } + + android { + applicationVariants.configureEach { + val variant = this + val outputDir = File(buildDir, "generateExternalFile/${'$'}{variant.dirName}") + val task = project.tasks.register("generateExternalFile${'$'}{variant.name.capitalize()}", FileGeneratingTask::class.java) { + this.outputDir.set(outputDir) + } + variant.registerJavaGeneratingTask(task, outputDir) + } + } + """.trimIndent() + ) + build(":app:compileDebugKotlinAndroidApp") { + assertTasksExecuted(":app:compileDebugKotlinAndroidApp") + } + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/AndroidProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/AndroidProjectHandler.kt index 4b433e947c9..2e72781f3b8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/AndroidProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/AndroidProjectHandler.kt @@ -231,10 +231,12 @@ internal class AndroidProjectHandler( val javaTask = variantData.javaCompileProvider @Suppress("UNCHECKED_CAST") val kotlinTask = compilation.compileTaskProvider as TaskProvider compilation.androidVariant.forEachJavaSourceDir { sources -> - kotlinTask.configure { - it.setSource(sources.dir) - it.dependsOn(sources) - } + // It is important to pass exactly `sources.dir` as provider with explicit task dependency + // Because of the following bugs: + // * https://github.com/gradle/gradle/issues/27881 ConfigurableFileTree.from() doesn't preserve Task Dependencies + // * https://github.com/gradle/gradle/issues/27882 SourceDirectorySet doesn't accept ConfigurableFileTree + val sourceDirWithTaskDependencies = project.filesProvider(sources) { sources.dir } + compilation.defaultSourceSet.kotlin.srcDir(sourceDirWithTaskDependencies) } wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask) }