Reduce overhead on wiring task inputs to Android layouts
^KT-53118 In Progress
This commit is contained in:
+5
-5
@@ -1027,12 +1027,12 @@ abstract class AbstractKotlinAndroidGradleTests : BaseGradleIT() {
|
||||
|
||||
project.projectDir.resolve("app/build.gradle").appendText(
|
||||
"""
|
||||
|
|
||||
|androidExtensions {
|
||||
| experimental = true
|
||||
|
|
||||
}
|
||||
""".trimMargin()
|
||||
|androidExtensions {
|
||||
| experimental = true
|
||||
|}
|
||||
|
|
||||
""".trimMargin()
|
||||
)
|
||||
|
||||
project.build("assembleDebug") {
|
||||
|
||||
-39
@@ -9,7 +9,6 @@ package org.jetbrains.kotlin.gradle.plugin
|
||||
import com.android.build.api.attributes.BuildTypeAttr
|
||||
import com.android.build.gradle.*
|
||||
import com.android.build.gradle.api.*
|
||||
import com.android.build.gradle.tasks.MergeResources
|
||||
import org.gradle.api.InvalidUserCodeException
|
||||
import org.gradle.api.NamedDomainObjectCollection
|
||||
import org.gradle.api.Project
|
||||
@@ -18,7 +17,6 @@ import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.attributes.Category
|
||||
import org.gradle.api.file.ConfigurableFileTree
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.plugins.InvalidPluginException
|
||||
@@ -375,43 +373,6 @@ internal fun forEachVariant(project: Project, action: (BaseVariant) -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseVariant.getResDirectories(): FileCollection {
|
||||
val getAllResourcesMethod =
|
||||
this::class.java.methods.firstOrNull { it.name == "getAllRawAndroidResources" }
|
||||
if (getAllResourcesMethod != null) {
|
||||
val allResources = getAllResourcesMethod.invoke(this) as FileCollection
|
||||
return allResources
|
||||
}
|
||||
|
||||
val project = mergeResources.project
|
||||
return project.files(Callable { mergeResources?.computeResourceSetList0() ?: emptyList() })
|
||||
}
|
||||
|
||||
//TODO A public API is expected for this purpose. Once it is available, use the public API
|
||||
private fun MergeResources.computeResourceSetList0(): List<File>? {
|
||||
val computeResourceSetListMethod = MergeResources::class.java.declaredMethods
|
||||
.firstOrNull { it.name == "computeResourceSetList" && it.parameterCount == 0 } ?: return null
|
||||
|
||||
val oldIsAccessible = computeResourceSetListMethod.isAccessible
|
||||
try {
|
||||
computeResourceSetListMethod.isAccessible = true
|
||||
|
||||
val resourceSets = computeResourceSetListMethod.invoke(this) as? Iterable<*>
|
||||
|
||||
return resourceSets
|
||||
?.mapNotNull { resourceSet ->
|
||||
val getSourceFiles = resourceSet?.javaClass?.methods?.find { it.name == "getSourceFiles" && it.parameterCount == 0 }
|
||||
val files = getSourceFiles?.invoke(resourceSet)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
files as? Iterable<File>
|
||||
}
|
||||
?.flatten()
|
||||
|
||||
} finally {
|
||||
computeResourceSetListMethod.isAccessible = oldIsAccessible
|
||||
}
|
||||
}
|
||||
|
||||
/** Filter for the AGP test variant classpath artifacts. */
|
||||
class AndroidTestedVariantArtifactsFilter(
|
||||
private val artifactCollection: ArtifactCollection,
|
||||
|
||||
+24
-56
@@ -13,12 +13,10 @@ import com.android.build.gradle.api.TestVariant
|
||||
import com.android.build.gradle.internal.variant.TestVariantData
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.ConfigurableFileTree
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.gradle.model.builder.KotlinAndroidExtensionModelBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||
@@ -130,31 +128,30 @@ class AndroidSubplugin : KotlinCompilerPluginSupportPlugin {
|
||||
)
|
||||
)
|
||||
kotlinCompilation.compileKotlinTaskProvider.configure {
|
||||
it.androidLayoutResourceFiles.from(getLayoutDirectories(project, sourceSet.res.srcDirs))
|
||||
it.androidLayoutResourceFiles.from(
|
||||
sourceSet.res.sourceDirectoryTrees.layoutDirectories
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
addVariant(mainSourceSet)
|
||||
|
||||
val flavorSourceSets = androidExtension.productFlavors
|
||||
.mapNotNull { androidExtension.sourceSets.findByName(it.name) }
|
||||
|
||||
for (sourceSet in flavorSourceSets) {
|
||||
addVariant(sourceSet)
|
||||
androidExtension.productFlavors.configureEach { flavor ->
|
||||
androidExtension.sourceSets.findByName(flavor.name)?.let {
|
||||
addVariant(it)
|
||||
}
|
||||
}
|
||||
|
||||
return project.provider { wrapPluginOptions(pluginOptions, "configuration") }
|
||||
}
|
||||
|
||||
private fun getLayoutDirectories(project: Project, resDirectories: Iterable<File>): FileCollection {
|
||||
fun isLayoutDirectory(file: File) = file.name == "layout" || file.name.startsWith("layout-")
|
||||
|
||||
return project.files(Callable {
|
||||
resDirectories.flatMap { resDir ->
|
||||
(resDir.listFiles(::isLayoutDirectory)).orEmpty().asList()
|
||||
private val List<ConfigurableFileTree>.layoutDirectories
|
||||
get() = map { tree ->
|
||||
tree.matching {
|
||||
it.include("**/layout/**")
|
||||
it.include("**/layout-*/**")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyExperimental(
|
||||
kotlinCompile: TaskProvider<out KotlinCompile>,
|
||||
@@ -178,55 +175,39 @@ class AndroidSubplugin : KotlinCompilerPluginSupportPlugin {
|
||||
val mainSourceSet = androidExtension.sourceSets.getByName("main")
|
||||
pluginOptions += SubpluginOption("package", getApplicationPackage(androidExtension, project, mainSourceSet))
|
||||
|
||||
fun addVariant(name: String, resDirectories: FileCollection) {
|
||||
fun addVariant(name: String, resDirectories: List<ConfigurableFileTree>) {
|
||||
val optionValue = lazy {
|
||||
buildString {
|
||||
append(name)
|
||||
append(';')
|
||||
resDirectories.joinTo(this, separator = ";") { it.canonicalPath }
|
||||
resDirectories.map { it.dir }.joinTo(this, separator = ";") { it.canonicalPath }
|
||||
}
|
||||
}
|
||||
pluginOptions += CompositeSubpluginOption(
|
||||
"variant", optionValue, listOf(
|
||||
SubpluginOption("variantName", name),
|
||||
// use INTERNAL option kind since the resources are tracked as sources (see below)
|
||||
FilesSubpluginOption("resDirs", resDirectories)
|
||||
FilesSubpluginOption(
|
||||
"resDirs",
|
||||
resDirectories.map { it.dir }
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
kotlinCompile.configure {
|
||||
it.inputs.files(getLayoutDirectories(project, resDirectories))
|
||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||
.withPropertyName("androidExtensionLayoutsFrom$name")
|
||||
.skipWhenEmpty(true)
|
||||
.run {
|
||||
if (GradleVersion.current() >= GradleVersion.version("6.8")) {
|
||||
ignoreEmptyDirectories()
|
||||
} else {
|
||||
this!!
|
||||
}
|
||||
}
|
||||
it.androidLayoutResourceFiles.from(resDirectories.layoutDirectories)
|
||||
}
|
||||
}
|
||||
|
||||
fun addSourceSetAsVariant(name: String) {
|
||||
val sourceSet = androidExtension.sourceSets.findByName(name) ?: return
|
||||
val srcDirs = sourceSet.res.srcDirs.toList()
|
||||
val srcDirs = sourceSet.res.sourceDirectoryTrees
|
||||
if (srcDirs.isNotEmpty()) {
|
||||
addVariant(sourceSet.name, project.files(srcDirs))
|
||||
addVariant(sourceSet.name, srcDirs)
|
||||
}
|
||||
}
|
||||
|
||||
val resDirectoriesForAllVariants = mutableListOf<FileCollection>()
|
||||
|
||||
forEachVariant(project) { variant ->
|
||||
if (getTestedVariantData(variant) != null) return@forEachVariant
|
||||
resDirectoriesForAllVariants += variant.getResDirectories()
|
||||
}
|
||||
|
||||
val commonResDirectories = getCommonResDirectories(project, resDirectoriesForAllVariants)
|
||||
|
||||
addVariant("main", commonResDirectories)
|
||||
addSourceSetAsVariant("main")
|
||||
|
||||
getVariantComponentNames(variantData)?.let { (variantName, flavorName, buildTypeName) ->
|
||||
addSourceSetAsVariant(buildTypeName)
|
||||
@@ -252,19 +233,6 @@ class AndroidSubplugin : KotlinCompilerPluginSupportPlugin {
|
||||
|
||||
private data class VariantComponentNames(val variantName: String, val flavorName: String, val buildTypeName: String)
|
||||
|
||||
private fun getCommonResDirectories(project: Project, resDirectories: List<FileCollection>): FileCollection {
|
||||
val lazyFiles = lazy {
|
||||
if (resDirectories.isEmpty()) {
|
||||
emptySet<File>()
|
||||
} else {
|
||||
resDirectories.first().toMutableSet().apply {
|
||||
resDirectories.drop(1).forEach { retainAll(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
return project.files(Callable { lazyFiles.value })
|
||||
}
|
||||
|
||||
private fun getApplicationPackage(androidExtension: BaseExtension, project: Project, mainSourceSet: AndroidSourceSet): String {
|
||||
val manifestFile = mainSourceSet.manifest.srcFile
|
||||
val applicationPackage = getApplicationPackage(androidExtension, manifestFile)
|
||||
|
||||
Reference in New Issue
Block a user