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(
|
project.projectDir.resolve("app/build.gradle").appendText(
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|androidExtensions {
|
|
||||||
| experimental = true
|
|
||||||
|
|
|
|
||||||
}
|
|androidExtensions {
|
||||||
""".trimMargin()
|
| experimental = true
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
""".trimMargin()
|
||||||
)
|
)
|
||||||
|
|
||||||
project.build("assembleDebug") {
|
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.api.attributes.BuildTypeAttr
|
||||||
import com.android.build.gradle.*
|
import com.android.build.gradle.*
|
||||||
import com.android.build.gradle.api.*
|
import com.android.build.gradle.api.*
|
||||||
import com.android.build.gradle.tasks.MergeResources
|
|
||||||
import org.gradle.api.InvalidUserCodeException
|
import org.gradle.api.InvalidUserCodeException
|
||||||
import org.gradle.api.NamedDomainObjectCollection
|
import org.gradle.api.NamedDomainObjectCollection
|
||||||
import org.gradle.api.Project
|
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.Attribute
|
||||||
import org.gradle.api.attributes.Category
|
import org.gradle.api.attributes.Category
|
||||||
import org.gradle.api.file.ConfigurableFileTree
|
import org.gradle.api.file.ConfigurableFileTree
|
||||||
import org.gradle.api.file.FileCollection
|
|
||||||
import org.gradle.api.file.SourceDirectorySet
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
import org.gradle.api.plugins.InvalidPluginException
|
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. */
|
/** Filter for the AGP test variant classpath artifacts. */
|
||||||
class AndroidTestedVariantArtifactsFilter(
|
class AndroidTestedVariantArtifactsFilter(
|
||||||
private val artifactCollection: ArtifactCollection,
|
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 com.android.build.gradle.internal.variant.TestVariantData
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
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.provider.Provider
|
||||||
import org.gradle.api.tasks.PathSensitivity
|
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
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.model.builder.KotlinAndroidExtensionModelBuilder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||||
@@ -130,31 +128,30 @@ class AndroidSubplugin : KotlinCompilerPluginSupportPlugin {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
kotlinCompilation.compileKotlinTaskProvider.configure {
|
kotlinCompilation.compileKotlinTaskProvider.configure {
|
||||||
it.androidLayoutResourceFiles.from(getLayoutDirectories(project, sourceSet.res.srcDirs))
|
it.androidLayoutResourceFiles.from(
|
||||||
|
sourceSet.res.sourceDirectoryTrees.layoutDirectories
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addVariant(mainSourceSet)
|
addVariant(mainSourceSet)
|
||||||
|
|
||||||
val flavorSourceSets = androidExtension.productFlavors
|
androidExtension.productFlavors.configureEach { flavor ->
|
||||||
.mapNotNull { androidExtension.sourceSets.findByName(it.name) }
|
androidExtension.sourceSets.findByName(flavor.name)?.let {
|
||||||
|
addVariant(it)
|
||||||
for (sourceSet in flavorSourceSets) {
|
}
|
||||||
addVariant(sourceSet)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return project.provider { wrapPluginOptions(pluginOptions, "configuration") }
|
return project.provider { wrapPluginOptions(pluginOptions, "configuration") }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLayoutDirectories(project: Project, resDirectories: Iterable<File>): FileCollection {
|
private val List<ConfigurableFileTree>.layoutDirectories
|
||||||
fun isLayoutDirectory(file: File) = file.name == "layout" || file.name.startsWith("layout-")
|
get() = map { tree ->
|
||||||
|
tree.matching {
|
||||||
return project.files(Callable {
|
it.include("**/layout/**")
|
||||||
resDirectories.flatMap { resDir ->
|
it.include("**/layout-*/**")
|
||||||
(resDir.listFiles(::isLayoutDirectory)).orEmpty().asList()
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun applyExperimental(
|
private fun applyExperimental(
|
||||||
kotlinCompile: TaskProvider<out KotlinCompile>,
|
kotlinCompile: TaskProvider<out KotlinCompile>,
|
||||||
@@ -178,55 +175,39 @@ class AndroidSubplugin : KotlinCompilerPluginSupportPlugin {
|
|||||||
val mainSourceSet = androidExtension.sourceSets.getByName("main")
|
val mainSourceSet = androidExtension.sourceSets.getByName("main")
|
||||||
pluginOptions += SubpluginOption("package", getApplicationPackage(androidExtension, project, mainSourceSet))
|
pluginOptions += SubpluginOption("package", getApplicationPackage(androidExtension, project, mainSourceSet))
|
||||||
|
|
||||||
fun addVariant(name: String, resDirectories: FileCollection) {
|
fun addVariant(name: String, resDirectories: List<ConfigurableFileTree>) {
|
||||||
val optionValue = lazy {
|
val optionValue = lazy {
|
||||||
buildString {
|
buildString {
|
||||||
append(name)
|
append(name)
|
||||||
append(';')
|
append(';')
|
||||||
resDirectories.joinTo(this, separator = ";") { it.canonicalPath }
|
resDirectories.map { it.dir }.joinTo(this, separator = ";") { it.canonicalPath }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pluginOptions += CompositeSubpluginOption(
|
pluginOptions += CompositeSubpluginOption(
|
||||||
"variant", optionValue, listOf(
|
"variant", optionValue, listOf(
|
||||||
SubpluginOption("variantName", name),
|
SubpluginOption("variantName", name),
|
||||||
// use INTERNAL option kind since the resources are tracked as sources (see below)
|
// use INTERNAL option kind since the resources are tracked as sources (see below)
|
||||||
FilesSubpluginOption("resDirs", resDirectories)
|
FilesSubpluginOption(
|
||||||
|
"resDirs",
|
||||||
|
resDirectories.map { it.dir }
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
kotlinCompile.configure {
|
kotlinCompile.configure {
|
||||||
it.inputs.files(getLayoutDirectories(project, resDirectories))
|
it.androidLayoutResourceFiles.from(resDirectories.layoutDirectories)
|
||||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
|
||||||
.withPropertyName("androidExtensionLayoutsFrom$name")
|
|
||||||
.skipWhenEmpty(true)
|
|
||||||
.run {
|
|
||||||
if (GradleVersion.current() >= GradleVersion.version("6.8")) {
|
|
||||||
ignoreEmptyDirectories()
|
|
||||||
} else {
|
|
||||||
this!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addSourceSetAsVariant(name: String) {
|
fun addSourceSetAsVariant(name: String) {
|
||||||
val sourceSet = androidExtension.sourceSets.findByName(name) ?: return
|
val sourceSet = androidExtension.sourceSets.findByName(name) ?: return
|
||||||
val srcDirs = sourceSet.res.srcDirs.toList()
|
val srcDirs = sourceSet.res.sourceDirectoryTrees
|
||||||
if (srcDirs.isNotEmpty()) {
|
if (srcDirs.isNotEmpty()) {
|
||||||
addVariant(sourceSet.name, project.files(srcDirs))
|
addVariant(sourceSet.name, srcDirs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val resDirectoriesForAllVariants = mutableListOf<FileCollection>()
|
addSourceSetAsVariant("main")
|
||||||
|
|
||||||
forEachVariant(project) { variant ->
|
|
||||||
if (getTestedVariantData(variant) != null) return@forEachVariant
|
|
||||||
resDirectoriesForAllVariants += variant.getResDirectories()
|
|
||||||
}
|
|
||||||
|
|
||||||
val commonResDirectories = getCommonResDirectories(project, resDirectoriesForAllVariants)
|
|
||||||
|
|
||||||
addVariant("main", commonResDirectories)
|
|
||||||
|
|
||||||
getVariantComponentNames(variantData)?.let { (variantName, flavorName, buildTypeName) ->
|
getVariantComponentNames(variantData)?.let { (variantName, flavorName, buildTypeName) ->
|
||||||
addSourceSetAsVariant(buildTypeName)
|
addSourceSetAsVariant(buildTypeName)
|
||||||
@@ -252,19 +233,6 @@ class AndroidSubplugin : KotlinCompilerPluginSupportPlugin {
|
|||||||
|
|
||||||
private data class VariantComponentNames(val variantName: String, val flavorName: String, val buildTypeName: String)
|
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 {
|
private fun getApplicationPackage(androidExtension: BaseExtension, project: Project, mainSourceSet: AndroidSourceSet): String {
|
||||||
val manifestFile = mainSourceSet.manifest.srcFile
|
val manifestFile = mainSourceSet.manifest.srcFile
|
||||||
val applicationPackage = getApplicationPackage(androidExtension, manifestFile)
|
val applicationPackage = getApplicationPackage(androidExtension, manifestFile)
|
||||||
|
|||||||
Reference in New Issue
Block a user