KT-41295: Friend paths and compiler options compatible with conf caching
This change fixes serialization of friend paths and it uses a file collection to record all friend paths. Also, when computing the tested classpath for android projects, we now avoid resolving the file collection until necessary. Fixes: KT-41295 Test: ConfigurationCacheForAndroidIT
This commit is contained in:
committed by
nataliya.valtman
parent
be916e556a
commit
162dc3aa0c
+6
@@ -41,6 +41,12 @@ class ConfigurationCacheForAndroidIT : AbstractConfigurationCacheIT() {
|
||||
testConfigurationCacheOf(":Lib:compileFlavor1DebugKotlin", ":Android:compileFlavor1DebugKotlin")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKotlinAndroidProjectTests() = with(Project("AndroidIncrementalMultiModule")) {
|
||||
applyAndroid40Alpha4KotlinVersionWorkaround()
|
||||
testConfigurationCacheOf(":app:compileDebugAndroidTestKotlin", ":app:compileDebugUnitTestKotlin")
|
||||
}
|
||||
|
||||
/**
|
||||
* Android Gradle plugin 4.0-alpha4 depends on the EAP versions of some o.j.k modules.
|
||||
* Force the current Kotlin version, so the EAP versions are not queried from the
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import com.example.AppDummy
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println(AppDummy())
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import com.example.AppDummy
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println(AppDummy())
|
||||
}
|
||||
+1
-1
@@ -99,7 +99,7 @@ internal open class KotlinJvmCompilerArgumentsContributor(
|
||||
args.moduleName = moduleName
|
||||
logger.kotlinDebug { "args.moduleName = ${args.moduleName}" }
|
||||
|
||||
args.friendPaths = friendPaths
|
||||
args.friendPaths = friendPaths.files.map { it.absolutePath }.toTypedArray()
|
||||
logger.kotlinDebug { "args.friendPaths = ${args.friendPaths?.joinToString() ?: "[]"}" }
|
||||
|
||||
if (DefaultsOnly in flags) return
|
||||
|
||||
+53
-13
@@ -11,9 +11,11 @@ import com.android.build.gradle.*
|
||||
import com.android.build.gradle.api.*
|
||||
import com.android.build.gradle.tasks.MergeResources
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ArtifactCollection
|
||||
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.specs.Spec
|
||||
import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
@@ -26,6 +28,9 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.thisTaskProvider
|
||||
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||
import java.io.File
|
||||
import java.io.ObjectInputStream
|
||||
import java.io.ObjectOutputStream
|
||||
import java.io.Serializable
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
class Android25ProjectHandler(
|
||||
@@ -65,20 +70,16 @@ class Android25ProjectHandler(
|
||||
}
|
||||
|
||||
// Find the classpath entries that come from the tested variant and register them as the friend paths, lazily
|
||||
val originalArtifactCollection = variantData.getCompileClasspathArtifacts(preJavaClasspathKey)
|
||||
val testedVariantDataIsNotNull = getTestedVariantData(variantData) != null
|
||||
val projectPath = project.path
|
||||
compilation.testedVariantArtifacts.set(
|
||||
project.files(
|
||||
project.provider {
|
||||
variantData.getCompileClasspathArtifacts(preJavaClasspathKey)
|
||||
.filter {
|
||||
it.id.componentIdentifier is TestedComponentIdentifier ||
|
||||
// If tests depend on the main classes transitively, through a test dependency on another module which
|
||||
// depends on this module, then there's no artifact with a TestedComponentIdentifier, so consider the artifact of the
|
||||
// current module a friend path, too:
|
||||
getTestedVariantData(variantData) != null &&
|
||||
(it.id.componentIdentifier as? ProjectComponentIdentifier)?.projectPath == project.path
|
||||
}
|
||||
.map { it.file }
|
||||
}
|
||||
originalArtifactCollection.artifactFiles.filter(
|
||||
AndroidTestedVariantArtifactsFilter(
|
||||
originalArtifactCollection,
|
||||
testedVariantDataIsNotNull,
|
||||
projectPath
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -213,4 +214,43 @@ private fun MergeResources.computeResourceSetList0(): List<File>? {
|
||||
} finally {
|
||||
computeResourceSetListMethod.isAccessible = oldIsAccessible
|
||||
}
|
||||
}
|
||||
|
||||
/** Filter for the AGP test variant classpath artifacts. */
|
||||
class AndroidTestedVariantArtifactsFilter(
|
||||
private val artifactCollection: ArtifactCollection,
|
||||
private val testedVariantDataIsNotNull: Boolean,
|
||||
private val projectPath: String
|
||||
) : Serializable, Spec<File> {
|
||||
|
||||
/** Make transient as it should be derived from the [artifactCollection] property which may change in configuration cached runs. */
|
||||
@Transient
|
||||
private var filteredFiles = initFilteredFiles()
|
||||
|
||||
private fun initFilteredFiles(): Lazy<Set<File>> {
|
||||
return lazy {
|
||||
artifactCollection.filter {
|
||||
it.id.componentIdentifier is TestedComponentIdentifier ||
|
||||
// If tests depend on the main classes transitively, through a test dependency on another module which
|
||||
// depends on this module, then there's no artifact with a TestedComponentIdentifier, so consider the artifact of the
|
||||
// current module a friend path, too:
|
||||
testedVariantDataIsNotNull &&
|
||||
(it.id.componentIdentifier as? ProjectComponentIdentifier)?.projectPath == projectPath
|
||||
}
|
||||
.mapTo(mutableSetOf()) { it.file }
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeObject(objectOutputStream: ObjectOutputStream) {
|
||||
objectOutputStream.defaultWriteObject()
|
||||
}
|
||||
|
||||
private fun readObject(objectInputStream: ObjectInputStream) {
|
||||
objectInputStream.defaultReadObject()
|
||||
filteredFiles = initFilteredFiles()
|
||||
}
|
||||
|
||||
override fun isSatisfiedBy(element: File): Boolean {
|
||||
return element in filteredFiles.value
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -70,7 +70,7 @@ open class KotlinCompileCommon : AbstractKotlinCompile<K2MetadataCompilerArgumen
|
||||
classpath = classpathList.joinToString(File.pathSeparator)
|
||||
destination = destinationDir.canonicalPath
|
||||
|
||||
friendPaths = this@KotlinCompileCommon.friendPaths
|
||||
friendPaths = this@KotlinCompileCommon.friendPaths.files.map { it.absolutePath }.toTypedArray()
|
||||
refinesPaths = refinesMetadataPaths.map { it.absolutePath }.toTypedArray()
|
||||
}
|
||||
|
||||
|
||||
+14
-13
@@ -288,15 +288,17 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
}
|
||||
|
||||
@get:Internal // takes part in the compiler arguments
|
||||
val friendPaths: Array<String> by project.provider {
|
||||
taskData.compilation.run {
|
||||
if (this !is AbstractKotlinCompilation<*>) return@run emptyArray<String>()
|
||||
associateWithTransitiveClosure
|
||||
.flatMap { it.output.classesDirs }
|
||||
.plus(friendArtifacts)
|
||||
.map { it.absolutePath }.toTypedArray()
|
||||
val friendPaths: FileCollection = project.files(
|
||||
project.provider {
|
||||
taskData.compilation.run {
|
||||
if (this !is AbstractKotlinCompilation<*>) return@run project.files()
|
||||
mutableListOf<FileCollection>().also { allCollections ->
|
||||
associateWithTransitiveClosure.forEach { allCollections.add(it.output.classesDirs) }
|
||||
allCollections.add(friendArtifacts)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
|
||||
|
||||
@@ -415,7 +417,7 @@ class KotlinJvmCompilerArgumentsProvider
|
||||
(taskProvider: KotlinCompile) : KotlinCompileArgumentsProvider<KotlinCompile>(taskProvider) {
|
||||
|
||||
val moduleName: String
|
||||
val friendPaths: Array<String>
|
||||
val friendPaths: FileCollection
|
||||
val compileClasspath: Iterable<File>
|
||||
val destinationDir: File
|
||||
internal val kotlinOptions: List<KotlinJvmOptionsImpl?>
|
||||
@@ -643,10 +645,9 @@ open class Kotlin2JsCompile : AbstractKotlinCompile<K2JSCompilerArguments>(), Ko
|
||||
internal val friendDependencies: List<String>
|
||||
get() {
|
||||
val filter = libraryFilter
|
||||
return friendPaths.filter {
|
||||
val file = File(it)
|
||||
file.exists() && filter(file)
|
||||
}
|
||||
return friendPaths.files.filter {
|
||||
it.exists() && filter(it)
|
||||
}.map { it.absolutePath }
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
|
||||
Reference in New Issue
Block a user