@ -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 :
@ -94,3 +105,14 @@ internal fun Project.fixAndroidLintTaskDependencies() {
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 " )
}
}
}
}