[Gradle] Associate Android java sources with related Kotlin Source Set

Java sources can be produced by the task or can be configured with
task dependencies. Previously sources were included into task directly
now they are properly configured with Kotlin Android Source Set.

^KT-63753 Verification Pending
^KT-65426 Verification Pending
This commit is contained in:
Anton Lakotka
2024-02-14 11:27:43 +01:00
committed by Space Team
parent b5ed2326e7
commit 020bb72d2b
8 changed files with 45 additions and 21 deletions
@@ -973,11 +973,6 @@ class KotlinAndroidMppIT : KGPBaseTest() {
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(
"""
@@ -28,7 +28,7 @@ internal val singleTargetAndroidSourceSetLayout = KotlinAndroidSourceSetLayout(
GradleConventionAddKotlinSourcesToAndroidSourceSetConfigurator,
Agp7AddKotlinSourcesToAndroidSourceSetConfigurator
.onlyIf { AndroidGradlePluginVersion.current >= "7.0.0" },
KotlinAndroidJavaSourceDirConfigurator,
SingleTargetSourceDirConfigurator,
),
checker = KotlinAndroidSourceSetLayoutChecker()
@@ -43,6 +43,7 @@ internal val multiplatformAndroidSourceSetLayoutV1 = KotlinAndroidSourceSetLayou
GradleConventionAddKotlinSourcesToAndroidSourceSetConfigurator,
Agp7AddKotlinSourcesToAndroidSourceSetConfigurator
.onlyIf { AndroidGradlePluginVersion.current >= "7.0.0" },
KotlinAndroidJavaSourceDirConfigurator,
MultiplatformAndroidResourceDirConfigurator,
MultiplatformLayoutV1DependsOnConfigurator,
MultiplatformLayoutV1SourceDirConfigurator
@@ -62,6 +63,7 @@ internal val multiplatformAndroidSourceSetLayoutV2 = KotlinAndroidSourceSetLayou
MultiplatformLayoutV2DependsOnConfigurator,
Agp7AddKotlinSourcesToAndroidSourceSetConfigurator
.onlyIf { AndroidGradlePluginVersion.current >= "7.0.0" },
KotlinAndroidJavaSourceDirConfigurator,
MultiplatformLayoutV2SourceDirConfigurator,
MultiplatformLayoutV2DefaultManifestLocationConfigurator
),
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2024 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.
*/
@file:Suppress("TYPEALIAS_EXPANSION_DEPRECATION")
package org.jetbrains.kotlin.gradle.plugin.sources.android.configurator
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.utils.DeprecatedAndroidSourceSet
import org.jetbrains.kotlin.gradle.utils.fileCollectionFromConfigurableFileTree
import org.jetbrains.kotlin.gradle.utils.filesProvider
internal object KotlinAndroidJavaSourceDirConfigurator : KotlinAndroidSourceSetConfigurator {
override fun configure(target: KotlinAndroidTarget, kotlinSourceSet: KotlinSourceSet, androidSourceSet: DeprecatedAndroidSourceSet) {
val project = target.project
kotlinSourceSet.kotlin.srcDir(project.provider {
// getSourceDirectoryTrees() is not lazy, thus it should be wrapped with provider
androidSourceSet.java.getSourceDirectoryTrees().map { sources ->
project.fileCollectionFromConfigurableFileTree(sources)
}
})
}
}
@@ -27,7 +27,5 @@ internal object MultiplatformLayoutV1SourceDirConfigurator : KotlinAndroidSource
if (!androidSourceSet.name.startsWith(target.disambiguationClassifier)) {
kotlinSourceSet.kotlin.srcDir("src/${androidSourceSet.name}/kotlin")
}
kotlinSourceSet.kotlin.srcDir(target.project.provider { androidSourceSet.java.srcDirs })
}
}
@@ -15,7 +15,6 @@ internal object MultiplatformLayoutV2SourceDirConfigurator : KotlinAndroidSource
kotlinSourceSet: KotlinSourceSet,
@Suppress("TYPEALIAS_EXPANSION_DEPRECATION") androidSourceSet: DeprecatedAndroidSourceSet
) {
kotlinSourceSet.kotlin.srcDir(target.project.provider { androidSourceSet.java.srcDirs })
kotlinSourceSet.kotlin.srcDir("src/${androidSourceSet.name}/kotlin")
}
}
@@ -16,6 +16,5 @@ internal object SingleTargetSourceDirConfigurator : KotlinAndroidSourceSetConfig
@Suppress("TYPEALIAS_EXPANSION_DEPRECATION") androidSourceSet: DeprecatedAndroidSourceSet
) {
kotlinSourceSet.kotlin.srcDir("src/${androidSourceSet.name}/kotlin")
kotlinSourceSet.kotlin.srcDir(target.project.provider { androidSourceSet.java.srcDirs })
}
}
@@ -230,13 +230,11 @@ internal class AndroidProjectHandler(
val javaTask = variantData.javaCompileProvider
@Suppress("UNCHECKED_CAST") val kotlinTask = compilation.compileTaskProvider as TaskProvider<KotlinCompile>
compilation.androidVariant.forEachJavaSourceDir { 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)
kotlinTask.configure { task ->
variantData.forEachJavaSourceDir { sources ->
task.source(sources.dir)
task.dependsOn(sources)
}
}
wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
}
@@ -6,9 +6,7 @@
package org.jetbrains.kotlin.gradle.utils
import org.gradle.api.Project
import org.gradle.api.file.Directory
import org.gradle.api.file.FileCollection
import org.gradle.api.file.RegularFile
import org.gradle.api.file.*
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.plugin.internal.CustomPropertiesFileValueSource
import org.jetbrains.kotlin.gradle.plugin.internal.configurationTimePropertiesAccessor
@@ -149,4 +147,12 @@ internal val Project.localProperties: Provider<Map<String, String>>
/**
* Returns file collection [this] excluding files from [excludes] if not null
*/
internal fun FileCollection.exclude(excludes: FileCollection?): FileCollection = if (excludes != null) minus(excludes) else this
internal fun FileCollection.exclude(excludes: FileCollection?): FileCollection = if (excludes != null) minus(excludes) else this
internal fun Project.fileCollectionFromConfigurableFileTree(fileTree: ConfigurableFileTree): ConfigurableFileCollection {
// It is important to pass exactly `fileTree.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
return project.filesProvider(fileTree) { fileTree.dir }
}