|
|
|
@ -1,18 +1,35 @@
|
|
|
|
|
package org.jetbrains.compose.resources |
|
|
|
|
|
|
|
|
|
import com.android.build.api.variant.AndroidComponentsExtension |
|
|
|
|
import com.android.build.gradle.BaseExtension |
|
|
|
|
import com.android.build.gradle.internal.tasks.ProcessJavaResTask |
|
|
|
|
import org.gradle.api.DefaultTask |
|
|
|
|
import org.gradle.api.Project |
|
|
|
|
import org.gradle.api.file.DirectoryProperty |
|
|
|
|
import org.gradle.api.file.FileSystemOperations |
|
|
|
|
import org.gradle.api.provider.Property |
|
|
|
|
import org.gradle.api.provider.Provider |
|
|
|
|
import org.gradle.api.tasks.SourceSet |
|
|
|
|
import org.gradle.api.tasks.* |
|
|
|
|
import org.jetbrains.compose.ComposePlugin |
|
|
|
|
import org.jetbrains.compose.desktop.application.internal.ComposeProperties |
|
|
|
|
import org.jetbrains.compose.internal.KOTLIN_JVM_PLUGIN_ID |
|
|
|
|
import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID |
|
|
|
|
import org.jetbrains.compose.internal.utils.* |
|
|
|
|
import org.jetbrains.compose.internal.utils.dependsOn |
|
|
|
|
import org.jetbrains.compose.internal.utils.registerTask |
|
|
|
|
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi |
|
|
|
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension |
|
|
|
|
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension |
|
|
|
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation |
|
|
|
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet |
|
|
|
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget |
|
|
|
|
import org.jetbrains.kotlin.gradle.plugin.sources.android.androidSourceSetInfoOrNull |
|
|
|
|
import org.jetbrains.kotlin.gradle.utils.ObservableSet |
|
|
|
|
import java.io.File |
|
|
|
|
import javax.inject.Inject |
|
|
|
|
|
|
|
|
|
internal const val COMPOSE_RESOURCES_DIR = "composeResources" |
|
|
|
|
private const val RES_GEN_DIR = "generated/compose/resourceGenerator" |
|
|
|
|
internal const val RES_GEN_DIR = "generated/compose/resourceGenerator" |
|
|
|
|
private val androidPluginIds = listOf( |
|
|
|
|
"com.android.application", |
|
|
|
|
"com.android.library" |
|
|
|
@ -20,27 +37,77 @@ private val androidPluginIds = listOf(
|
|
|
|
|
|
|
|
|
|
internal fun Project.configureComposeResources() { |
|
|
|
|
plugins.withId(KOTLIN_MPP_PLUGIN_ID) { |
|
|
|
|
configureComposeResources(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) |
|
|
|
|
val kotlinExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java) |
|
|
|
|
configureComposeResources(kotlinExtension, KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) |
|
|
|
|
|
|
|
|
|
//when applied AGP then configure android resources |
|
|
|
|
androidPluginIds.forEach { pluginId -> |
|
|
|
|
plugins.withId(pluginId) { |
|
|
|
|
val androidExtension = project.extensions.getByType(BaseExtension::class.java) |
|
|
|
|
configureAndroidComposeResources(kotlinExtension, androidExtension) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
plugins.withId(KOTLIN_JVM_PLUGIN_ID) { |
|
|
|
|
configureComposeResources(SourceSet.MAIN_SOURCE_SET_NAME) |
|
|
|
|
val kotlinExtension = project.extensions.getByType(KotlinProjectExtension::class.java) |
|
|
|
|
configureComposeResources(kotlinExtension, SourceSet.MAIN_SOURCE_SET_NAME) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun Project.configureComposeResources(commonSourceSetName: String) { |
|
|
|
|
val kotlinExtension = project.extensions.getByType(KotlinProjectExtension::class.java) |
|
|
|
|
private fun Project.configureComposeResources(kotlinExtension: KotlinProjectExtension, commonSourceSetName: String) { |
|
|
|
|
kotlinExtension.sourceSets.all { sourceSet -> |
|
|
|
|
val sourceSetName = sourceSet.name |
|
|
|
|
val composeResourcesPath = project.projectDir.resolve("src/$sourceSetName/$COMPOSE_RESOURCES_DIR") |
|
|
|
|
|
|
|
|
|
//To compose resources will be packed to a final artefact we need to mark them as resources |
|
|
|
|
//sourceSet.resources works for all targets except ANDROID! |
|
|
|
|
sourceSet.resources.srcDirs(composeResourcesPath) |
|
|
|
|
|
|
|
|
|
if (sourceSetName == commonSourceSetName) { |
|
|
|
|
configureResourceGenerator(composeResourcesPath, sourceSet) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@OptIn(ExperimentalKotlinGradlePluginApi::class) |
|
|
|
|
private fun Project.configureAndroidComposeResources( |
|
|
|
|
kotlinExtension: KotlinMultiplatformExtension, |
|
|
|
|
androidExtension: BaseExtension |
|
|
|
|
) { |
|
|
|
|
//mark all composeResources as Android resources |
|
|
|
|
kotlinExtension.targets.matching { it is KotlinAndroidTarget }.all { androidTarget -> |
|
|
|
|
androidTarget.compilations.all { compilation: KotlinCompilation<*> -> |
|
|
|
|
compilation.defaultSourceSet.androidSourceSetInfoOrNull?.let { kotlinAndroidSourceSet -> |
|
|
|
|
androidExtension.sourceSets |
|
|
|
|
.matching { it.name == kotlinAndroidSourceSet.androidSourceSetName } |
|
|
|
|
.all { androidSourceSet -> |
|
|
|
|
(compilation.allKotlinSourceSets as ObservableSet<KotlinSourceSet>).forAll { kotlinSourceSet -> |
|
|
|
|
androidSourceSet.resources.srcDir( |
|
|
|
|
projectDir.resolve("src/${kotlinSourceSet.name}/$COMPOSE_RESOURCES_DIR") |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//copy fonts from the compose resources dir to android assets |
|
|
|
|
val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return |
|
|
|
|
val commonResourcesDir = projectDir.resolve("src/${KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME}/$COMPOSE_RESOURCES_DIR") |
|
|
|
|
androidComponents.onVariants { variant -> |
|
|
|
|
val copyFonts = registerTask<CopyAndroidFontsToAssetsTask>( |
|
|
|
|
"copy${variant.name.uppercaseFirstChar()}FontsToAndroidAssets" |
|
|
|
|
) { |
|
|
|
|
from.set(commonResourcesDir) |
|
|
|
|
} |
|
|
|
|
variant.sources?.assets?.addGeneratedSourceDirectory( |
|
|
|
|
taskProvider = copyFonts, |
|
|
|
|
wiredWith = CopyAndroidFontsToAssetsTask::outputDirectory |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun Project.configureResourceGenerator(commonComposeResourcesDir: File, commonSourceSet: KotlinSourceSet) { |
|
|
|
|
val commonComposeResources = provider { commonComposeResourcesDir } |
|
|
|
|
val packageName = provider { |
|
|
|
|
buildString { |
|
|
|
|
val group = project.group.toString().lowercase().asUnderscoredIdentifier() |
|
|
|
@ -73,7 +140,7 @@ private fun Project.configureResourceGenerator(commonComposeResourcesDir: File,
|
|
|
|
|
) { |
|
|
|
|
it.packageName.set(packageName) |
|
|
|
|
it.shouldGenerateResClass.set(shouldGenerateResClass) |
|
|
|
|
it.resDir.set(commonComposeResources) |
|
|
|
|
it.resDir.set(commonComposeResourcesDir) |
|
|
|
|
it.codeDir.set(buildDir("$RES_GEN_DIR/kotlin")) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -86,15 +153,26 @@ private fun Project.configureResourceGenerator(commonComposeResourcesDir: File,
|
|
|
|
|
it.dependsOn(genTask) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//when applied AGP then configure android resources |
|
|
|
|
androidPluginIds.forEach { pluginId -> |
|
|
|
|
plugins.withId(pluginId) { |
|
|
|
|
configureAndroidResources( |
|
|
|
|
commonComposeResources, |
|
|
|
|
buildDir("$RES_GEN_DIR/androidFonts").map { it.asFile }, |
|
|
|
|
shouldGenerateResClass |
|
|
|
|
) |
|
|
|
|
//Copy task doesn't work with 'variant.sources?.assets?.addGeneratedSourceDirectory' API |
|
|
|
|
internal abstract class CopyAndroidFontsToAssetsTask : DefaultTask() { |
|
|
|
|
@get:Inject |
|
|
|
|
abstract val fileSystem: FileSystemOperations |
|
|
|
|
|
|
|
|
|
@get:Input |
|
|
|
|
abstract val from: Property<File> |
|
|
|
|
|
|
|
|
|
@get:OutputDirectory |
|
|
|
|
abstract val outputDirectory: DirectoryProperty |
|
|
|
|
|
|
|
|
|
@TaskAction |
|
|
|
|
fun action() { |
|
|
|
|
fileSystem.copy { |
|
|
|
|
it.includeEmptyDirs = false |
|
|
|
|
it.from(from) |
|
|
|
|
it.exclude("**/font*/*") |
|
|
|
|
it.into(outputDirectory) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |