You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
6.4 KiB
137 lines
6.4 KiB
package org.jetbrains.compose.resources |
|
|
|
import org.gradle.api.Project |
|
import org.gradle.api.file.Directory |
|
import org.gradle.api.plugins.ExtensionAware |
|
import org.gradle.api.provider.Provider |
|
import org.gradle.api.tasks.Copy |
|
import org.jetbrains.compose.desktop.application.internal.ComposeProperties |
|
import org.jetbrains.compose.internal.utils.* |
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension |
|
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension |
|
import org.jetbrains.kotlin.gradle.plugin.mpp.* |
|
import org.jetbrains.kotlin.konan.target.KonanTarget |
|
import java.io.File |
|
|
|
private const val COCOAPODS_PLUGIN_ID = "org.jetbrains.kotlin.native.cocoapods" |
|
private const val IOS_COMPOSE_RESOURCES_ROOT_DIR = "compose-resources" |
|
|
|
internal fun Project.configureSyncIosComposeResources( |
|
kotlinExtension: KotlinMultiplatformExtension |
|
) { |
|
if (ComposeProperties.dontSyncResources(project).get()) { |
|
logger.info( |
|
"Compose Multiplatform resource management for iOS is disabled: " + |
|
"'${ComposeProperties.SYNC_RESOURCES_PROPERTY}' value is 'false'" |
|
) |
|
return |
|
} |
|
|
|
kotlinExtension.targets.withType(KotlinNativeTarget::class.java).all { nativeTarget -> |
|
if (nativeTarget.isIosTarget()) { |
|
nativeTarget.binaries.withType(Framework::class.java).all { iosFramework -> |
|
val frameworkClassifier = iosFramework.getClassifier() |
|
val checkNoSandboxTask = tasks.registerOrConfigure<CheckCanAccessComposeResourcesDirectory>( |
|
"checkCanSync${frameworkClassifier}ComposeResourcesForIos" |
|
) {} |
|
|
|
val frameworkResources = files() |
|
iosFramework.compilation.allKotlinSourceSets.forAll { ss -> |
|
frameworkResources.from(ss.resources.sourceDirectories) |
|
} |
|
val syncComposeResourcesTask = tasks.registerOrConfigure<SyncComposeResourcesForIosTask>( |
|
iosFramework.getSyncResourcesTaskName() |
|
) { |
|
dependsOn(checkNoSandboxTask) |
|
dependsOn(frameworkResources) //!!! explicit dependency because targetResources is not an input |
|
|
|
outputDir.set(iosFramework.getFinalResourcesDir()) |
|
targetResources.put(iosFramework.target.konanTarget.name, frameworkResources) |
|
} |
|
|
|
val externalTaskName = if (iosFramework.isCocoapodsFramework()) { |
|
"syncFramework" |
|
} else { |
|
"embedAndSign${frameworkClassifier}AppleFrameworkForXcode" |
|
} |
|
|
|
project.tasks.configureEach { task -> |
|
if (task.name == externalTaskName) { |
|
task.dependsOn(syncComposeResourcesTask) |
|
} |
|
} |
|
} |
|
|
|
nativeTarget.binaries.withType(TestExecutable::class.java).all { testExec -> |
|
val copyTestResourcesTask = tasks.registerOrConfigure<Copy>( |
|
"copyTestComposeResourcesFor${testExec.target.targetName.uppercaseFirstChar()}" |
|
) { |
|
from({ |
|
(testExec.compilation.associatedCompilations + testExec.compilation).flatMap { compilation -> |
|
compilation.allKotlinSourceSets.map { it.resources } |
|
} |
|
}) |
|
into(testExec.outputDirectory.resolve(IOS_COMPOSE_RESOURCES_ROOT_DIR)) |
|
} |
|
testExec.linkTask.dependsOn(copyTestResourcesTask) |
|
} |
|
} |
|
} |
|
|
|
plugins.withId(COCOAPODS_PLUGIN_ID) { |
|
(kotlinExtension as ExtensionAware).extensions.getByType(CocoapodsExtension::class.java).apply { |
|
framework { podFramework -> |
|
val syncDir = podFramework.getFinalResourcesDir().get().asFile.relativeTo(projectDir) |
|
val specAttr = "['${syncDir.path}']" |
|
extraSpecAttributes["resources"] = specAttr |
|
project.tasks.named("podInstall").configure { |
|
it.doFirst { |
|
if (extraSpecAttributes["resources"] != specAttr) { |
|
error(""" |
|
|Kotlin.cocoapods.extraSpecAttributes["resources"] is not compatible with Compose Multiplatform's resources management for iOS. |
|
| * Recommended action: remove extraSpecAttributes["resources"] from '${project.buildFile}' and run '${project.path}:podInstall' once; |
|
| * Alternative action: turn off Compose Multiplatform's resources management for iOS by adding '${ComposeProperties.SYNC_RESOURCES_PROPERTY}=false' to your gradle.properties; |
|
""".trimMargin()) |
|
} |
|
syncDir.mkdirs() |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
private fun Framework.getClassifier(): String { |
|
val suffix = joinLowerCamelCase(buildType.getName(), outputKind.taskNameClassifier) |
|
return if (name == suffix) "" |
|
else name.substringBeforeLast(suffix.uppercaseFirstChar()).uppercaseFirstChar() |
|
} |
|
|
|
internal fun Framework.getSyncResourcesTaskName() = "sync${getClassifier()}ComposeResourcesForIos" |
|
private fun Framework.isCocoapodsFramework() = name.startsWith("pod") |
|
|
|
private fun Framework.getFinalResourcesDir(): Provider<Directory> { |
|
val providers = project.providers |
|
return if (isCocoapodsFramework()) { |
|
project.layout.buildDirectory.dir("compose/ios/$baseName/$IOS_COMPOSE_RESOURCES_ROOT_DIR/") |
|
} else { |
|
providers.environmentVariable("BUILT_PRODUCTS_DIR") |
|
.zip( |
|
providers.environmentVariable("CONTENTS_FOLDER_PATH") |
|
) { builtProductsDir, contentsFolderPath -> |
|
File("$builtProductsDir/$contentsFolderPath/$IOS_COMPOSE_RESOURCES_ROOT_DIR").canonicalPath |
|
} |
|
.flatMap { |
|
project.objects.directoryProperty().apply { set(File(it)) } |
|
} |
|
} |
|
} |
|
|
|
private fun KotlinNativeTarget.isIosSimulatorTarget(): Boolean = |
|
konanTarget === KonanTarget.IOS_X64 || konanTarget === KonanTarget.IOS_SIMULATOR_ARM64 |
|
|
|
private fun KotlinNativeTarget.isIosDeviceTarget(): Boolean = |
|
konanTarget === KonanTarget.IOS_ARM64 || konanTarget === KonanTarget.IOS_ARM32 |
|
|
|
private fun KotlinNativeTarget.isIosTarget(): Boolean = |
|
isIosSimulatorTarget() || isIosDeviceTarget() |