Skip to content

Commit

Permalink
[gradle] Restore correct android assets registration after AGP fix. (#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
terrakok authored Aug 14, 2024
1 parent 481bb53 commit 48b64fd
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import com.android.build.api.variant.AndroidComponentsExtension
import com.android.build.api.variant.Variant
import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask
import com.android.build.gradle.internal.lint.LintModelWriterTask
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.Copy
import org.jetbrains.compose.internal.utils.dir
import org.gradle.api.file.FileSystemOperations
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.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import javax.inject.Inject

internal fun Project.getAndroidVariantComposeResources(
private fun Project.getAndroidVariantComposeResources(
kotlinExtension: KotlinMultiplatformExtension,
variant: Variant
): FileCollection = project.files({
Expand All @@ -27,46 +35,27 @@ internal fun Project.getAndroidVariantComposeResources(
}
})

internal fun Project.getKgpAndroidVariantComposeResources(
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
) {
internal fun Project.configureAndroidComposeResources() {
//copy all compose resources to android assets
val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return
val kotlinExtension = project.extensions.findByType(KotlinMultiplatformExtension::class.java) ?: return
androidComponents.onVariants { variant ->
val camelVariantName = variant.name.uppercaseFirstChar()
val variantAssets = getVariantComposeResources(variant)
val variantAssetsDir = layout.buildDirectory.dir(RES_GEN_DIR).dir(variant.name + "AndroidAssets")
val variantAssets = getAndroidVariantComposeResources(kotlinExtension, variant)

val copyVariantAssets = tasks.register(
"copy${camelVariantName}ComposeResourcesToAndroidAssets",
Copy::class.java
) { task ->
task.from(variantAssets)
task.into(variantAssetsDir)
val copyVariantAssets = registerTask<CopyResourcesToAndroidAssetsTask>(
"copy${camelVariantName}ComposeResourcesToAndroidAssets"
) {
from.set(variantAssets)
}

//https://issuetracker.google.com/348208777
val staticDir = variantAssetsDir.get().asFile
staticDir.mkdirs()
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",
variant.sources.assets?.addGeneratedSourceDirectory(
copyVariantAssets,
CopyResourcesToAndroidAssetsTask::outputDirectory
)
tasks.configureEach { task ->
if (task.name in agpTaskNames) {
//fix agp task dependencies for AndroidStudio preview
if (task.name == "compile${camelVariantName}Sources") {
task.dependsOn(copyVariantAssets)
}
//fix linter task dependencies for `build` task
Expand All @@ -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:
Expand All @@ -93,4 +104,15 @@ internal fun Project.fixAndroidLintTaskDependencies() {
}.configureEach {
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")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,7 @@ private fun Project.onKgpApplied(config: Provider<ResourcesExtension>, kgp: Kotl
if (kmpResourcesAreAvailable) {
configureKmpResources(kotlinExtension, extraProperties.get(KMP_RES_EXT)!!, config)
onAgpApplied {
//workaround to fix AndroidStudio preview works with compose resources:
//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)
}
fixKgpAndroidPreviewTaskDependencies()
fixAndroidLintTaskDependencies()
}
} else {
Expand All @@ -69,9 +63,7 @@ private fun Project.onKgpApplied(config: Provider<ResourcesExtension>, kgp: Kotl
configureComposeResources(kotlinExtension, commonMain, config)

onAgpApplied {
configureAndroidComposeResources { variant ->
getAndroidVariantComposeResources(kotlinExtension, variant)
}
configureAndroidComposeResources()
fixAndroidLintTaskDependencies()
}
}
Expand Down

0 comments on commit 48b64fd

Please sign in to comment.