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.
108 lines
4.1 KiB
108 lines
4.1 KiB
/* |
|
* Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. |
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. |
|
*/ |
|
|
|
package org.jetbrains.compose.resources.ios |
|
|
|
import org.gradle.api.file.DirectoryProperty |
|
import org.gradle.api.file.FileCollection |
|
import org.gradle.api.provider.Provider |
|
import org.gradle.api.provider.SetProperty |
|
import org.gradle.api.tasks.* |
|
import org.jetbrains.compose.experimental.uikit.tasks.AbstractComposeIosTask |
|
import org.jetbrains.compose.internal.utils.clearDirs |
|
import java.io.File |
|
import kotlin.io.path.Path |
|
import kotlin.io.path.pathString |
|
import kotlin.io.path.relativeTo |
|
|
|
abstract class SyncComposeResourcesForIosTask : AbstractComposeIosTask() { |
|
|
|
private fun Provider<String>.orElseThrowMissingAttributeError(attribute: String): Provider<String> { |
|
val noProvidedValue = "__NO_PROVIDED_VALUE__" |
|
return this.orElse(noProvidedValue).map { |
|
if (it == noProvidedValue) { |
|
error( |
|
"Could not infer iOS target $attribute. Make sure to build " + |
|
"via XCode (directly or via Kotlin Multiplatform Mobile plugin for Android Studio)") |
|
} |
|
it |
|
} |
|
} |
|
|
|
@get:Input |
|
val xcodeTargetPlatform: Provider<String> = |
|
providers.gradleProperty("compose.ios.resources.platform") |
|
.orElse(providers.environmentVariable("PLATFORM_NAME")) |
|
.orElseThrowMissingAttributeError("platform") |
|
|
|
|
|
@get:Input |
|
val xcodeTargetArchs: Provider<List<String>> = |
|
providers.gradleProperty("compose.ios.resources.archs") |
|
.orElse(providers.environmentVariable("ARCHS")) |
|
.orElseThrowMissingAttributeError("architectures") |
|
.map { |
|
it.split(",", " ").filter { it.isNotBlank() } |
|
} |
|
|
|
@get:Input |
|
internal val iosTargets: SetProperty<IosTargetResources> = objects.setProperty(IosTargetResources::class.java) |
|
|
|
@get:PathSensitive(PathSensitivity.ABSOLUTE) |
|
@get:InputFiles |
|
val resourceFiles: Provider<FileCollection> = xcodeTargetPlatform.zip(xcodeTargetArchs, ::Pair) |
|
.map { (xcodeTargetPlatform, xcodeTargetArchs) -> |
|
val allResources = objects.fileCollection() |
|
val activeKonanTargets = determineIosKonanTargetsFromEnv(xcodeTargetPlatform, xcodeTargetArchs) |
|
.mapTo(HashSet()) { it.name } |
|
val dirsToInclude = iosTargets.get() |
|
.filter { it.konanTarget.get() in activeKonanTargets } |
|
.flatMapTo(HashSet()) { it.dirs.get() } |
|
for (dirPath in dirsToInclude) { |
|
val fileTree = objects.fileTree().apply { |
|
setDir(layout.projectDirectory.dir(dirPath)) |
|
include("**/*") |
|
} |
|
allResources.from(fileTree) |
|
} |
|
allResources |
|
} |
|
|
|
@get:OutputDirectory |
|
val outputDir: DirectoryProperty = objects.directoryProperty() |
|
|
|
@TaskAction |
|
fun run() { |
|
val outputDir = outputDir.get().asFile |
|
fileOperations.clearDirs(outputDir) |
|
val allResourceDirs = iosTargets.get().flatMapTo(HashSet()) { it.dirs.get().map { Path(it).toAbsolutePath() } } |
|
|
|
fun copyFileToOutputDir(file: File) { |
|
for (dir in allResourceDirs) { |
|
val path = file.toPath().toAbsolutePath() |
|
if (path.startsWith(dir)) { |
|
val targetFile = outputDir.resolve(path.relativeTo(dir).pathString) |
|
file.copyTo(targetFile, overwrite = true) |
|
return |
|
} |
|
} |
|
|
|
error( |
|
buildString { |
|
appendLine("Resource file '$file' does not belong to a known resource directory:") |
|
allResourceDirs.forEach { |
|
appendLine("* $it") |
|
} |
|
} |
|
) |
|
} |
|
|
|
val resourceFiles = resourceFiles.get().files |
|
for (file in resourceFiles) { |
|
copyFileToOutputDir(file) |
|
} |
|
logger.info("Synced Compose resource files. Copied ${resourceFiles.size} files to $outputDir") |
|
} |
|
}
|
|
|