Browse Source

[gradle] Restore correct android assets registration after AGP fix. (#5118)

After the fix there will be a correct configuration cache usage.  
Fixes https://youtrack.jetbrains.com/issue/CMP-5674

## Release Notes
### Fixes - Gradle Plugin
- _(prerelease fix)_ Fix broken configuration cache due Android Studio +
AGP issues. Now Android Studio previews require latest AGP versions
(8.5.2, 8.6.0-rc01, 8.7.0-alpha04):
https://issuetracker.google.com/issues/348208777
release/1.7.0-alpha03 v1.7.0-alpha03
Konstantin 3 months ago committed by GitHub
parent
commit
48b64fdece
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 90
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt
  2. 12
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt

90
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt

@ -4,15 +4,23 @@ import com.android.build.api.variant.AndroidComponentsExtension
import com.android.build.api.variant.Variant import com.android.build.api.variant.Variant
import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask
import com.android.build.gradle.internal.lint.LintModelWriterTask import com.android.build.gradle.internal.lint.LintModelWriterTask
import org.gradle.api.DefaultTask
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.Copy import org.gradle.api.file.FileSystemOperations
import org.jetbrains.compose.internal.utils.dir import org.gradle.api.provider.Property
import org.gradle.api.tasks.IgnoreEmptyDirectories
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.jetbrains.compose.internal.utils.registerTask
import org.jetbrains.compose.internal.utils.uppercaseFirstChar import org.jetbrains.compose.internal.utils.uppercaseFirstChar
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import javax.inject.Inject
internal fun Project.getAndroidVariantComposeResources( private fun Project.getAndroidVariantComposeResources(
kotlinExtension: KotlinMultiplatformExtension, kotlinExtension: KotlinMultiplatformExtension,
variant: Variant variant: Variant
): FileCollection = project.files({ ): FileCollection = project.files({
@ -27,46 +35,27 @@ internal fun Project.getAndroidVariantComposeResources(
} }
}) })
internal fun Project.getKgpAndroidVariantComposeResources( internal fun Project.configureAndroidComposeResources() {
variant: Variant
): FileCollection = project.files({
val taskName = "${variant.name}AssetsCopyForAGP"
if (tasks.names.contains(taskName)) tasks.named(taskName).map { it.outputs.files }
else files()
})
internal fun Project.configureAndroidComposeResources(
getVariantComposeResources: (Variant) -> FileCollection
) {
//copy all compose resources to android assets //copy all compose resources to android assets
val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return
val kotlinExtension = project.extensions.findByType(KotlinMultiplatformExtension::class.java) ?: return
androidComponents.onVariants { variant -> androidComponents.onVariants { variant ->
val camelVariantName = variant.name.uppercaseFirstChar() val camelVariantName = variant.name.uppercaseFirstChar()
val variantAssets = getVariantComposeResources(variant) val variantAssets = getAndroidVariantComposeResources(kotlinExtension, variant)
val variantAssetsDir = layout.buildDirectory.dir(RES_GEN_DIR).dir(variant.name + "AndroidAssets")
val copyVariantAssets = tasks.register( val copyVariantAssets = registerTask<CopyResourcesToAndroidAssetsTask>(
"copy${camelVariantName}ComposeResourcesToAndroidAssets", "copy${camelVariantName}ComposeResourcesToAndroidAssets"
Copy::class.java ) {
) { task -> from.set(variantAssets)
task.from(variantAssets)
task.into(variantAssetsDir)
} }
//https://issuetracker.google.com/348208777 variant.sources.assets?.addGeneratedSourceDirectory(
val staticDir = variantAssetsDir.get().asFile copyVariantAssets,
staticDir.mkdirs() CopyResourcesToAndroidAssetsTask::outputDirectory
variant.sources.assets?.addStaticSourceDirectory(staticDir.path)
val agpTaskNames = listOf(
//fix agp task dependencies for build and allTests tasks
"merge${camelVariantName}Assets",
"package${camelVariantName}Assets",
//fix agp task dependencies for AndroidStudio preview
"compile${camelVariantName}Sources",
) )
tasks.configureEach { task -> tasks.configureEach { task ->
if (task.name in agpTaskNames) { //fix agp task dependencies for AndroidStudio preview
if (task.name == "compile${camelVariantName}Sources") {
task.dependsOn(copyVariantAssets) task.dependsOn(copyVariantAssets)
} }
//fix linter task dependencies for `build` task //fix linter task dependencies for `build` task
@ -77,6 +66,28 @@ internal fun Project.configureAndroidComposeResources(
} }
} }
//Copy task doesn't work with 'variant.sources?.assets?.addGeneratedSourceDirectory' API
internal abstract class CopyResourcesToAndroidAssetsTask : DefaultTask() {
@get:Inject
abstract val fileSystem: FileSystemOperations
@get:InputFiles
@get:IgnoreEmptyDirectories
abstract val from: Property<FileCollection>
@get:OutputDirectory
abstract val outputDirectory: DirectoryProperty
@TaskAction
fun action() {
fileSystem.copy {
it.includeEmptyDirs = false
it.from(from)
it.into(outputDirectory)
}
}
}
/* /*
There is a dirty fix for the problem: There is a dirty fix for the problem:
@ -93,4 +104,15 @@ internal fun Project.fixAndroidLintTaskDependencies() {
}.configureEach { }.configureEach {
it.mustRunAfter(tasks.withType(GenerateResourceAccessorsTask::class.java)) it.mustRunAfter(tasks.withType(GenerateResourceAccessorsTask::class.java))
} }
}
internal fun Project.fixKgpAndroidPreviewTaskDependencies() {
val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return
androidComponents.onVariants { variant ->
tasks.configureEach { task ->
if (task.name == "compile${variant.name.uppercaseFirstChar()}Sources") {
task.dependsOn("${variant.name}AssetsCopyForAGP")
}
}
}
} }

12
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt

@ -40,13 +40,7 @@ private fun Project.onKgpApplied(config: Provider<ResourcesExtension>, kgp: Kotl
if (kmpResourcesAreAvailable) { if (kmpResourcesAreAvailable) {
configureKmpResources(kotlinExtension, extraProperties.get(KMP_RES_EXT)!!, config) configureKmpResources(kotlinExtension, extraProperties.get(KMP_RES_EXT)!!, config)
onAgpApplied { onAgpApplied {
//workaround to fix AndroidStudio preview works with compose resources: fixKgpAndroidPreviewTaskDependencies()
//it copies android assets and mark it as a static assets dir
//yes, the same resources will be registered in AGP twice: from KGP and here as static dirs
//but it works fine and there are no problems during merge android assets
configureAndroidComposeResources { variant ->
getKgpAndroidVariantComposeResources(variant)
}
fixAndroidLintTaskDependencies() fixAndroidLintTaskDependencies()
} }
} else { } else {
@ -69,9 +63,7 @@ private fun Project.onKgpApplied(config: Provider<ResourcesExtension>, kgp: Kotl
configureComposeResources(kotlinExtension, commonMain, config) configureComposeResources(kotlinExtension, commonMain, config)
onAgpApplied { onAgpApplied {
configureAndroidComposeResources { variant -> configureAndroidComposeResources()
getAndroidVariantComposeResources(kotlinExtension, variant)
}
fixAndroidLintTaskDependencies() fixAndroidLintTaskDependencies()
} }
} }

Loading…
Cancel
Save