diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/SkieGradlePlugin.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/SkieGradlePlugin.kt index f454e72ee..6bd85ed50 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/SkieGradlePlugin.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/SkieGradlePlugin.kt @@ -8,28 +8,27 @@ import co.touchlab.skie.plugin.coroutines.registerConfigureMinOsVersionTaskIfNee import co.touchlab.skie.plugin.defaultarguments.disableCachingIfNeeded import co.touchlab.skie.plugin.dependencies.SkieCompilerPluginDependencyProvider import co.touchlab.skie.plugin.directory.SkieDirectoriesManager -import co.touchlab.skie.plugin.directory.skieDirectories import co.touchlab.skie.plugin.fatframework.FatFrameworkConfigurator import co.touchlab.skie.plugin.subplugin.SkieSubPluginManager import co.touchlab.skie.plugin.switflink.SwiftLinkingConfigurator -import co.touchlab.skie.plugin.util.appleTargets -import co.touchlab.skie.plugin.util.frameworks -import co.touchlab.skie.plugin.util.subpluginOption +import co.touchlab.skie.plugin.util.* import co.touchlab.skie.util.plugin.SkiePlugin import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink +import org.jetbrains.kotlin.gradle.dsl.KotlinNativeArtifact +import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.kotlinArtifactsExtension import org.jetbrains.kotlin.konan.target.HostManager abstract class SkieGradlePlugin : Plugin { override fun apply(project: Project) { + project.extensions.create("skieInternal", SkieInternalExtension::class.java) + project.configureSkieGradlePlugin() project.afterEvaluate { + project.configureRuntimeVariantFallback() project.configureSkieCompilerPlugin() } } @@ -38,6 +37,15 @@ abstract class SkieGradlePlugin : Plugin { SkieSubPluginManager.configureDependenciesForSubPlugins(project) } + private fun Project.configureRuntimeVariantFallback() { + if (!skieInternal.runtimeVariantFallback.isPresent) { + val extraPropertiesKey = "skieRuntimeVariantFallback" + skieInternal.runtimeVariantFallback.set( + project.properties[extraPropertiesKey]?.toString().toBoolean() + ) + } + } + private fun Project.configureSkieCompilerPlugin() { if (!isSkieEnabled) { return @@ -47,69 +55,74 @@ abstract class SkieGradlePlugin : Plugin { FatFrameworkConfigurator.configureSkieForFatFrameworks(project) - configureEachKotlinFrameworkLinkTask { - configureSkieForLinkTask() + kotlinMultiplatformExtension?.appleTargets?.all { + val target = this + binaries.all { + val binary = this + skieInternal.targets.add( + SkieTarget.TargetBinary( + project = project, + target = target, + binary = binary, + ) + ) + } + } + + kotlinArtifactsExtension.artifacts.withType().all { + skieInternal.targets.addAll(skieTargetsOf(this)) + } + + skieInternal.targets.all { + configureSkie() } } - private fun KotlinNativeLink.configureSkieForLinkTask() { + private fun SkieTarget.configureSkie() { SkieDirectoriesManager.configureCreateSkieBuildDirectoryTask(this) GradleAnalyticsManager(project).configureAnalytics(this) - disableCachingIfNeeded() - binary.target.addDependencyOnSkieRuntime() - binary.registerConfigureMinOsVersionTaskIfNeeded() + registerConfigureMinOsVersionTaskIfNeeded() CreateSkieConfigurationTask.registerTask(this) SwiftLinkingConfigurator.configureCustomSwiftLinking(this) + disableCachingIfNeeded() + + addDependencyOnSkieRuntime() + SkieSubPluginManager.registerSubPlugins(this) configureKotlinCompiler() } - private fun KotlinNativeLink.configureKotlinCompiler() { - compilerPluginClasspath = listOfNotNull( - compilerPluginClasspath, - SkieCompilerPluginDependencyProvider.getOrCreateDependencyConfiguration(project), - ).reduce(FileCollection::plus) - - compilerPluginOptions.addPluginArgument( + private fun SkieTarget.configureKotlinCompiler() { + addPluginArgument( SkiePlugin.id, - SkiePlugin.Options.skieDirectories.subpluginOption(skieDirectories), + SkiePlugin.Options.skieDirectories.subpluginOption(skieDirectories.get()), ) - } -} -internal fun Project.warnOnEmptyFrameworks() { - val hasFrameworks = extensions.findByType(KotlinMultiplatformExtension::class.java)?.appleTargets?.any { it.frameworks.isNotEmpty() } ?: false - if (!hasFrameworks) { - logger.warn("w: No Apple frameworks configured. Make sure you applied SKIE plugin in the correct module.") + addToCompilerClasspath( + SkieCompilerPluginDependencyProvider.getOrCreateDependencyConfiguration(project) + ) } } -internal fun Project.configureEachKotlinFrameworkLinkTask( - configure: KotlinNativeLink.() -> Unit, -) { - configureEachKotlinAppleTarget { - frameworks.forEach { framework -> - // Cannot use configure on linkTaskProvider because it's not possible to register new tasks in configure block of another task - configure(framework.linkTask) +internal fun Project.warnOnEmptyFrameworks() { + gradle.taskGraph.whenReady { + if (skieInternal.targets.isEmpty()) { + logger.warn("w: No Apple frameworks configured in module ${this@warnOnEmptyFrameworks.path}. Make sure you applied SKIE plugin in the correct module.") } } } -internal fun Project.configureEachKotlinAppleTarget( - configure: KotlinNativeTarget.() -> Unit, -) { - val kotlinExtension = extensions.findByType(KotlinMultiplatformExtension::class.java) ?: return - - kotlinExtension.appleTargets.forEach { - configure(it) - } -} - private val Project.isSkieEnabled: Boolean get() = project.skieExtension.isEnabled.get() && HostManager.hostIsMac + +internal val Project.kotlinMultiplatformExtension: KotlinMultiplatformExtension? + get() = project.extensions.findByType(KotlinMultiplatformExtension::class.java) + +internal val Project.skieInternal: SkieInternalExtension + get() = project.extensions.getByType(SkieInternalExtension::class.java) diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/SkieInternalExtension.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/SkieInternalExtension.kt new file mode 100644 index 000000000..d398cb727 --- /dev/null +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/SkieInternalExtension.kt @@ -0,0 +1,13 @@ +package co.touchlab.skie.plugin + +import co.touchlab.skie.plugin.util.SkieTarget +import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import javax.inject.Inject + +internal interface SkieInternalExtension { + val targets: NamedDomainObjectContainer + + val runtimeVariantFallback: Property +} diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/analytics/GradleAnalyticsManager.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/analytics/GradleAnalyticsManager.kt index 8bbafa758..1e5e22d77 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/analytics/GradleAnalyticsManager.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/analytics/GradleAnalyticsManager.kt @@ -1,5 +1,6 @@ package co.touchlab.skie.plugin.analytics +import co.touchlab.skie.plugin.util.SkieTarget import co.touchlab.skie.plugin.analytics.environment.GradleEnvironmentAnalytics import co.touchlab.skie.plugin.analytics.git.GitAnalytics import co.touchlab.skie.plugin.analytics.hardware.HardwareAnalytics @@ -8,58 +9,53 @@ import co.touchlab.skie.plugin.analytics.project.ProjectAnalytics import co.touchlab.skie.plugin.configuration.SkieExtension.Companion.buildConfiguration import co.touchlab.skie.plugin.configuration.skieExtension import co.touchlab.skie.plugin.directory.createSkieBuildDirectoryTask -import co.touchlab.skie.plugin.directory.skieDirectories -import co.touchlab.skie.plugin.util.doFirstOptimized -import co.touchlab.skie.plugin.util.doLastOptimized -import co.touchlab.skie.plugin.util.registerSkieLinkBasedTask +import co.touchlab.skie.plugin.util.* +import co.touchlab.skie.plugin.util.registerSkieTargetBasedTask import org.gradle.api.Project import org.gradle.api.provider.Provider -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink import java.time.Duration internal class GradleAnalyticsManager( private val project: Project, ) { - fun configureAnalytics(linkTask: KotlinNativeLink) { - val analyticsCollectorProvider = project.provider { + fun configureAnalytics(target: SkieTarget) { + val analyticsCollectorProvider = target.skieDirectories.map { skieDirectories -> AnalyticsCollector( - skieBuildDirectory = linkTask.skieDirectories.buildDirectory, + skieBuildDirectory = skieDirectories.buildDirectory, skieConfiguration = project.skieExtension.buildConfiguration(), ) } - configureUploadAnalyticsTask(linkTask) + configureUploadAnalyticsTask(target) - registerAnalyticsProducers(linkTask, analyticsCollectorProvider) + registerAnalyticsProducers(target, analyticsCollectorProvider) } - private fun configureUploadAnalyticsTask(linkTask: KotlinNativeLink) { - val uploadTask = linkTask.registerSkieLinkBasedTask("uploadAnalytics") { - this.analyticsDirectory.set(linkTask.skieDirectories.buildDirectory.analytics.directory) - this.applicationSupportDirectory.set(linkTask.skieDirectories.applicationSupport) + private fun configureUploadAnalyticsTask(target: SkieTarget) { + val uploadTask = target.registerSkieTargetBasedTask("uploadAnalytics") { + this.analyticsDirectory.set(target.skieDirectories.map { it.buildDirectory.analytics.directory }) + this.applicationSupportDirectory.set(target.skieDirectories.map { it.applicationSupport }) - dependsOn(linkTask.createSkieBuildDirectoryTask) - } - - linkTask.finalizedBy(uploadTask) + dependsOn(target.createSkieBuildDirectoryTask) - linkTask.project.afterEvaluate { - uploadTask.configure { - onlyIf { - val analyticsConfiguration = project.skieExtension.analytics + onlyIf { + val analyticsConfiguration = project.skieExtension.analytics - analyticsConfiguration.enabled.get() && !analyticsConfiguration.disableUpload.get() - } + analyticsConfiguration.enabled.get() && !analyticsConfiguration.disableUpload.get() } } + + target.task.configure { + finalizedBy(uploadTask) + } } private fun registerAnalyticsProducers( - linkTask: KotlinNativeLink, + target: SkieTarget, analyticsCollectorProvider: Provider, ) { - linkTask.doFirstOptimized { + target.task.configureDoFirstOptimized { analyticsCollectorProvider.get().collectAsync( GradleEnvironmentAnalytics.Producer(project), @@ -71,20 +67,20 @@ internal class GradleAnalyticsManager( ) } - registerPerformanceAnalyticsProducer(linkTask, analyticsCollectorProvider) + registerPerformanceAnalyticsProducer(target, analyticsCollectorProvider) } private fun registerPerformanceAnalyticsProducer( - linkTask: KotlinNativeLink, + target: SkieTarget, analyticsCollectorProvider: Provider, ) { var start: Long = 0 - linkTask.doFirstOptimized { + target.task.configureDoFirstOptimized { start = System.currentTimeMillis() } - linkTask.doLastOptimized { + target.task.configureDoLastOptimized { val linkTaskDuration = Duration.ofMillis(System.currentTimeMillis() - start) analyticsCollectorProvider.get().collectSynchronously( diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/configuration/CreateSkieConfigurationTask.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/configuration/CreateSkieConfigurationTask.kt index 815021f36..9b64e9975 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/configuration/CreateSkieConfigurationTask.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/configuration/CreateSkieConfigurationTask.kt @@ -1,15 +1,16 @@ package co.touchlab.skie.plugin.configuration +import co.touchlab.skie.plugin.util.SkieTarget import co.touchlab.skie.plugin.configuration.SkieExtension.Companion.buildConfiguration import co.touchlab.skie.plugin.directory.createSkieBuildDirectoryTask -import co.touchlab.skie.plugin.directory.skieBuildDirectory -import co.touchlab.skie.plugin.util.registerSkieLinkBasedTask +import co.touchlab.skie.plugin.util.registerSkieTargetBasedTask +import co.touchlab.skie.plugin.util.skieBuildDirectory +import co.touchlab.skie.plugin.util.skieConfiguration import groovy.json.JsonOutput import org.gradle.api.DefaultTask import org.gradle.api.provider.Property import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink import java.io.File internal abstract class CreateSkieConfigurationTask : DefaultTask() { @@ -35,14 +36,16 @@ internal abstract class CreateSkieConfigurationTask : DefaultTask() { companion object { - fun registerTask(linkTask: KotlinNativeLink) { - val createConfiguration = linkTask.registerSkieLinkBasedTask("createConfiguration") { - configurationFile.set(linkTask.skieBuildDirectory.skieConfiguration) + fun registerTask(target: SkieTarget) { + val createConfiguration = target.registerSkieTargetBasedTask("createConfiguration") { + configurationFile.set(target.skieBuildDirectory.skieConfiguration) - dependsOn(linkTask.createSkieBuildDirectoryTask) + dependsOn(target.createSkieBuildDirectoryTask) } - linkTask.inputs.files(createConfiguration.map { it.outputs }) + target.task.configure { + inputs.files(createConfiguration.map { it.outputs }) + } } } } diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/AddDependencyOnSkieRuntime.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/AddDependencyOnSkieRuntime.kt index 0240937ee..df9bff025 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/AddDependencyOnSkieRuntime.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/AddDependencyOnSkieRuntime.kt @@ -1,30 +1,39 @@ package co.touchlab.skie.plugin.coroutines -import co.touchlab.skie.gradle.KotlinCompilerVersion import co.touchlab.skie.gradle_plugin.BuildConfig -import co.touchlab.skie.plugin.util.named -import co.touchlab.skie.plugin.util.withType +import co.touchlab.skie.plugin.util.SkieTarget +import co.touchlab.skie.plugin.skieInternal +import co.touchlab.skie.plugin.util.lowerCamelCaseName import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractNativeLibrary -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.presetName -internal fun KotlinNativeTarget.addDependencyOnSkieRuntime() { - if (!project.isCoroutinesInteropEnabled) { - return +internal fun SkieTarget.addDependencyOnSkieRuntime() { + val configurationNames = when (this) { + is SkieTarget.TargetBinary -> listOfNotNull( + binary.compilation.apiConfigurationName, + (binary as? AbstractNativeLibrary)?.exportConfigurationName, + ) + is SkieTarget.Artifact -> listOf( + lowerCamelCaseName(konanTarget.presetName, artifact.artifactName, "linkLibrary"), + lowerCamelCaseName(konanTarget.presetName, artifact.artifactName, "linkExport"), + ) } - compilations.named("main") { - defaultSourceSet.dependencies { - api(BuildConfig.RUNTIME_DEPENDENCY(konanTarget, BuildConfig.KOTLIN_TOOLING_VERSION)) - } + val dependency = if (project.skieInternal.runtimeVariantFallback.get()) { + BuildConfig.DEFAULT_RUNTIME_DEPENDENCY + } else { + BuildConfig.SPECIFIC_RUNTIME_DEPENDENCY(konanTarget, BuildConfig.KOTLIN_TOOLING_VERSION) } - - binaries.withType().configureEach { - export(BuildConfig.RUNTIME_DEPENDENCY(konanTarget, BuildConfig.KOTLIN_TOOLING_VERSION)) + configurationNames.forEach { configurationName -> + project.dependencies.add(configurationName, dependency) } } -private fun BuildConfig.RUNTIME_DEPENDENCY(konanTarget: KonanTarget, kotlinVersion: String): String { +private val BuildConfig.DEFAULT_RUNTIME_DEPENDENCY: String + get() = "$RUNTIME_DEPENDENCY_GROUP:$RUNTIME_DEPENDENCY_NAME:$RUNTIME_DEPENDENCY_VERSION" + +private fun BuildConfig.SPECIFIC_RUNTIME_DEPENDENCY(konanTarget: KonanTarget, kotlinVersion: String): String { return "$RUNTIME_DEPENDENCY_GROUP:$RUNTIME_DEPENDENCY_NAME-${konanTarget.presetName}__kgp_${kotlinVersion}:$RUNTIME_DEPENDENCY_VERSION" } diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/ConfigureMinOsVersionTask.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/ConfigureMinOsVersionTask.kt index c784e22c8..c41e86ebd 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/ConfigureMinOsVersionTask.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/ConfigureMinOsVersionTask.kt @@ -1,13 +1,17 @@ package co.touchlab.skie.plugin.coroutines +import co.touchlab.skie.plugin.util.SkieTarget import co.touchlab.skie.plugin.util.getKonanHome import co.touchlab.skie.util.version.getMinRequiredOsVersionForSwiftAsync import co.touchlab.skie.util.version.isLowerVersionThan import org.gradle.api.DefaultTask +import org.gradle.api.Project import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBinary +import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.KotlinNativeLinkArtifactTask import org.jetbrains.kotlin.konan.properties.resolvablePropertyString import org.jetbrains.kotlin.konan.target.Distribution import org.jetbrains.kotlin.konan.target.KonanTarget @@ -16,39 +20,70 @@ import java.util.Properties internal abstract class ConfigureMinOsVersionTask : DefaultTask() { @get:Internal - abstract val binary: Property + abstract val target: Property @TaskAction fun runTask() { - val binary = binary.get() - val konanTarget = binary.target.konanTarget - val distribution = binary.distribution + val target = target.get() + val konanTarget = target.konanTarget + val distribution = target.distribution.get() fun overrideVersion(name: String) { val currentMinVersion = distribution.properties.targetString(name, konanTarget) val minRequiredVersion = getMinRequiredOsVersionForSwiftAsync(konanTarget.name) if (currentMinVersion == null || currentMinVersion.isLowerVersionThan(minRequiredVersion)) { - binary.freeCompilerArgs += listOf("$overrideKonanPropertiesKey=${name}.${konanTarget.name}=$minRequiredVersion") + target.addFreeCompilerArgs("$overrideKonanPropertiesKey=${name}.${konanTarget.name}=$minRequiredVersion") } } overrideVersion("osVersionMin") overrideVersion("osVersionMinSinceXcode15") } + + sealed interface NativeBinaryOrArtifact { + data class Binary(val binary: NativeBinary): NativeBinaryOrArtifact + data class Artifact(val task: KotlinNativeLinkArtifactTask): NativeBinaryOrArtifact + + val project: Project + get() = when (this) { + is Binary -> binary.project + is Artifact -> task.project + } + + val konanTarget: KonanTarget + get() = when (this) { + is Binary -> binary.target.konanTarget + is Artifact -> task.konanTarget + } + + var freeCompilerArgs: List + get() = when (this) { + is Binary -> binary.freeCompilerArgs + is Artifact -> task.toolOptions.freeCompilerArgs.get() + } + set(value) { + when (this) { + is Binary -> binary.freeCompilerArgs = value + is Artifact -> task.toolOptions.freeCompilerArgs.set(value) + } + } + + + } } +private val SkieTarget.distribution: Provider + get() = freeCompilerArgs.map { + val overrideKonanProperties = parseOverrideKonanProperties(it) + Distribution(konanHome = project.getKonanHome().absolutePath, propertyOverrides = overrideKonanProperties) + } + private fun Properties.targetString(name: String, target: KonanTarget): String? = resolvablePropertyString(name, target.name) private const val overrideKonanPropertiesKey = "-Xoverride-konan-properties" -private val NativeBinary.distribution: Distribution - get() { - val overrideKonanProperties = parseOverrideKonanProperties(freeCompilerArgs) - - return Distribution(konanHome = project.getKonanHome().absolutePath, propertyOverrides = overrideKonanProperties) - } private fun parseOverrideKonanProperties( arguments: List, diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/ConfigureMinOsVersions.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/ConfigureMinOsVersions.kt index 32de9b74f..94f5b794b 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/ConfigureMinOsVersions.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/ConfigureMinOsVersions.kt @@ -1,16 +1,18 @@ package co.touchlab.skie.plugin.coroutines -import co.touchlab.skie.plugin.util.registerSkieLinkBasedTask -import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBinary +import co.touchlab.skie.plugin.util.SkieTarget +import co.touchlab.skie.plugin.util.registerSkieTargetBasedTask -internal fun NativeBinary.registerConfigureMinOsVersionTaskIfNeeded() { +internal fun SkieTarget.registerConfigureMinOsVersionTaskIfNeeded() { if (!project.isCoroutinesInteropEnabled) { return } - val task = linkTask.registerSkieLinkBasedTask("configureMinOsVersion") { - this.binary.set(this@registerConfigureMinOsVersionTaskIfNeeded) + val configureMinOsVersionTask = registerSkieTargetBasedTask("configureMinOsVersion") { + this.target.set(this@registerConfigureMinOsVersionTaskIfNeeded) } - linkTask.dependsOn(task) + task.configure { + dependsOn(configureMinOsVersionTask) + } } diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/defaultarguments/DisableCachingForDefaultArguments.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/defaultarguments/DisableCachingForDefaultArguments.kt index d31f37f4d..4f82aefa3 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/defaultarguments/DisableCachingForDefaultArguments.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/defaultarguments/DisableCachingForDefaultArguments.kt @@ -1,13 +1,13 @@ package co.touchlab.skie.plugin.defaultarguments +import co.touchlab.skie.plugin.util.SkieTarget import co.touchlab.skie.plugin.configuration.skieExtension import org.gradle.api.Project import org.jetbrains.kotlin.konan.target.presetName -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink -fun KotlinNativeLink.disableCachingIfNeeded() { +fun SkieTarget.disableCachingIfNeeded() { if (project.areDefaultArgumentsInCachedLibrariesEnabled) { - project.extensions.extraProperties.set("kotlin.native.cacheKind.${binary.target.konanTarget.presetName}", "none") + project.extensions.extraProperties.set("kotlin.native.cacheKind.${konanTarget.presetName}", "none") } } diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/directory/SkieDirectoriesManager.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/directory/SkieDirectoriesManager.kt index 7aa7ff455..c9f2e29fb 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/directory/SkieDirectoriesManager.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/directory/SkieDirectoriesManager.kt @@ -1,8 +1,8 @@ package co.touchlab.skie.plugin.directory -import co.touchlab.skie.plugin.util.registerSkieLinkBasedTask -import co.touchlab.skie.plugin.util.skieLinkTaskName -import co.touchlab.skie.util.directory.SkieBuildDirectory +import co.touchlab.skie.plugin.util.SkieTarget +import co.touchlab.skie.plugin.util.registerSkieTargetBasedTask +import co.touchlab.skie.plugin.util.skieTargetBasedTaskName import co.touchlab.skie.util.directory.SkieDirectories import org.gradle.api.DefaultTask import org.gradle.api.Task @@ -11,16 +11,15 @@ import org.gradle.api.provider.Property import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskProvider -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink import javax.inject.Inject internal object SkieDirectoriesManager { const val baseTaskName: String = "createSkieDirectories" - fun configureCreateSkieBuildDirectoryTask(linkTask: KotlinNativeLink) { - linkTask.registerSkieLinkBasedTask(baseTaskName) { - skieDirectories.set(linkTask.skieDirectories) + fun configureCreateSkieBuildDirectoryTask(target: SkieTarget) { + target.registerSkieTargetBasedTask(baseTaskName) { + skieDirectories.set(target.skieDirectories) } } @@ -43,13 +42,5 @@ internal object SkieDirectoriesManager { } } -val KotlinNativeLink.skieDirectories: SkieDirectories - get() = SkieDirectories( - project.layout.buildDirectory.dir("skie/${binary.name}/${binary.target.targetName}").get().asFile, - ) - -val KotlinNativeLink.skieBuildDirectory: SkieBuildDirectory - get() = skieDirectories.buildDirectory - -internal val KotlinNativeLink.createSkieBuildDirectoryTask: TaskProvider - get() = project.tasks.named(skieLinkTaskName(SkieDirectoriesManager.baseTaskName)) +internal val SkieTarget.createSkieBuildDirectoryTask: TaskProvider + get() = project.tasks.named(skieTargetBasedTaskName(SkieDirectoriesManager.baseTaskName)) diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/subplugin/SkieSubPluginManager.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/subplugin/SkieSubPluginManager.kt index 55760e6a9..5e2f3c679 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/subplugin/SkieSubPluginManager.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/subplugin/SkieSubPluginManager.kt @@ -1,5 +1,6 @@ package co.touchlab.skie.plugin.subplugin +import co.touchlab.skie.plugin.util.SkieTarget import co.touchlab.skie.plugin.util.exclude import co.touchlab.skie.plugin.util.named import co.touchlab.skie.plugin.util.withType @@ -8,9 +9,6 @@ import org.gradle.api.Project import org.gradle.api.attributes.Category import org.gradle.api.attributes.LibraryElements import org.gradle.api.attributes.Usage -import org.gradle.api.file.FileCollection -import org.jetbrains.kotlin.gradle.plugin.mpp.Framework -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink internal object SkieSubPluginManager { @@ -37,29 +35,24 @@ internal object SkieSubPluginManager { } } - fun registerSubPlugins(linkTask: KotlinNativeLink) { - val framework = linkTask.binary as? Framework ?: return + fun registerSubPlugins(target: SkieTarget) { + target.registerSubPluginsOptions() - linkTask.registerSubPluginsOptions(framework) - - linkTask.registerSubPluginsToClasspath() + target.registerSubPluginsToClasspath() } - private fun KotlinNativeLink.registerSubPluginsOptions(framework: Framework) { + private fun SkieTarget.registerSubPluginsOptions() { project.skieSubPlugins.forEach { subPlugin -> - val options = subPlugin.getOptions(project, framework) + val options = subPlugin.getOptions(project, this) options.get().forEach { - compilerPluginOptions.addPluginArgument(subPlugin.compilerPluginId, it) + addPluginArgument(subPlugin.compilerPluginId, it) } } } - private fun KotlinNativeLink.registerSubPluginsToClasspath() { - compilerPluginClasspath = listOfNotNull( - compilerPluginClasspath, - project.configurations.getByName(subPluginConfigurationName), - ).reduce(FileCollection::plus) + private fun SkieTarget.registerSubPluginsToClasspath() { + addToCompilerClasspath(project.configurations.getByName(subPluginConfigurationName)) } } diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/subplugin/SkieSubplugin.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/subplugin/SkieSubplugin.kt index f7e0ca6a3..7cbb18acb 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/subplugin/SkieSubplugin.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/subplugin/SkieSubplugin.kt @@ -1,11 +1,11 @@ package co.touchlab.skie.plugin.subplugin +import co.touchlab.skie.plugin.util.SkieTarget import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.provider.Provider import org.jetbrains.kotlin.gradle.plugin.SubpluginOption -import org.jetbrains.kotlin.gradle.plugin.mpp.Framework interface SkieSubplugin : Plugin { @@ -13,7 +13,7 @@ interface SkieSubplugin : Plugin { override fun apply(target: Project) {} - fun getOptions(project: Project, framework: Framework): Provider> = + fun getOptions(project: Project, target: SkieTarget): Provider> = project.provider { emptyList() } fun configureDependencies(project: Project, pluginConfiguration: Configuration) diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/switflink/SwiftLinkingConfigurator.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/switflink/SwiftLinkingConfigurator.kt index 6534ea3da..1ead98bea 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/switflink/SwiftLinkingConfigurator.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/switflink/SwiftLinkingConfigurator.kt @@ -1,8 +1,9 @@ package co.touchlab.skie.plugin.switflink +import co.touchlab.skie.plugin.util.SkieTarget +import co.touchlab.skie.plugin.util.skieBuildDirectory import co.touchlab.skie.plugin.directory.createSkieBuildDirectoryTask -import co.touchlab.skie.plugin.directory.skieBuildDirectory -import co.touchlab.skie.plugin.util.registerSkieLinkBasedTask +import co.touchlab.skie.plugin.util.registerSkieTargetBasedTask import co.touchlab.skie.util.cache.syncDirectoryContentIfDifferent import org.gradle.api.DefaultTask import org.gradle.api.Project @@ -14,18 +15,20 @@ import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.Sync import org.gradle.api.tasks.TaskAction import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink import java.io.File internal object SwiftLinkingConfigurator { - fun configureCustomSwiftLinking(linkTask: KotlinNativeLink) { - with(linkTask.project) { - val swiftSourceSets = linkTask.binary.compilation.allKotlinSourceSets.map { createSwiftSourceSet(it) } + fun configureCustomSwiftLinking(target: SkieTarget) { + // TODO: Change this so that it bundles Swift directly to klib + if (target is SkieTarget.TargetBinary) { + with(target.project) { + val swiftSourceSets = target.binary.compilation.allKotlinSourceSets.map { createSwiftSourceSet(it) } - val swiftSources = objects.fileCollection().from(swiftSourceSets) + val swiftSources = objects.fileCollection().from(swiftSourceSets) - registerCustomSwiftTasks(linkTask, swiftSources) + registerCustomSwiftTasks(target, swiftSources) + } } } @@ -42,26 +45,28 @@ internal object SwiftLinkingConfigurator { get() = "src/$name/swift" private fun registerCustomSwiftTasks( - linkTask: KotlinNativeLink, + target: SkieTarget.TargetBinary, swiftSources: ConfigurableFileCollection?, ) { - val mergeTask = linkTask.registerSkieLinkBasedTask("mergeCustomSwift") { + val mergeTask = target.registerSkieTargetBasedTask("mergeCustomSwift") { from(swiftSources) - into(linkTask.skieBuildDirectory.temp.gradle.mergedCustomSwift.directory) + into(target.skieBuildDirectory.map { it.temp.gradle.mergedCustomSwift.directory }) - dependsOn(linkTask.createSkieBuildDirectoryTask) + dependsOn(target.createSkieBuildDirectoryTask) } - val syncTask = linkTask.registerSkieLinkBasedTask("packageCustomSwift") { + val syncTask = target.registerSkieTargetBasedTask("packageCustomSwift") { inputDirectory.set(mergeTask.map { it.outputs.files.singleFile }) - outputDirectory.set(linkTask.skieBuildDirectory.swift.custom.directory) + outputDirectory.set(target.skieBuildDirectory.map { it.swift.custom.directory }) - dependsOn(linkTask.createSkieBuildDirectoryTask) + dependsOn(target.createSkieBuildDirectoryTask) } - linkTask.inputs.files(syncTask.map { it.outputs.files }) + target.task.configure { + inputs.files(syncTask.map { it.outputs.files }) + } } abstract class SkieMergeCustomSwiftTask : Sync() { diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/BaseSkieTask.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/BaseSkieTask.kt index 0d45545c0..eb55637bf 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/BaseSkieTask.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/BaseSkieTask.kt @@ -3,22 +3,106 @@ package co.touchlab.skie.plugin.util import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.tasks.TaskProvider -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink +import org.jetbrains.kotlin.gradle.dsl.* -internal inline fun KotlinNativeLink.registerSkieLinkBasedTask( +internal fun SkieTarget.skieTargetBasedTaskName(baseName: String): String { + val linkTaskNameWithoutPrefix = when (this) { + is SkieTarget.TargetBinary -> task.name.removePrefix("link") + is SkieTarget.Artifact -> task.name.removePrefix("assemble") + } + return lowerCamelCaseName( + "skie", + baseName, + linkTaskNameWithoutPrefix, + ) +} + +internal fun Project.skieTargetsOf(artifact: KotlinNativeArtifact): List { + return when (artifact) { + is KotlinNativeLibrary -> if (artifact.target.family.isAppleFamily) { + artifact.modes.map { buildType -> + SkieTarget.Artifact( + project = this, + artifact = artifact, + konanTarget = artifact.target, + buildType = buildType, + ) + } + } else { + emptyList() + } + + is KotlinNativeFramework -> if (artifact.target.family.isAppleFamily) { + artifact.modes.map { buildType -> + SkieTarget.Artifact( + project = this, + artifact = artifact, + konanTarget = artifact.target, + buildType = buildType, + ) + } + } else { + emptyList() + } + + is KotlinNativeFatFramework -> artifact.modes.flatMap { buildType -> + artifact.targets.filter { it.family.isAppleFamily }.map { target -> + SkieTarget.Artifact( + project = this, + artifact = artifact, + konanTarget = target, + buildType = buildType, + ) + } + } + + is KotlinNativeXCFramework -> artifact.modes.flatMap { buildType -> + artifact.targets.filter { it.family.isAppleFamily }.map { target -> + SkieTarget.Artifact( + project = this, + artifact = artifact, + konanTarget = target, + buildType = buildType, + ) + } + } + else -> error("Unknown KotlinNativeArtifact type: $this") + } +} + +internal fun lowerCamelCaseName(vararg nameParts: String?): String { + val nonEmptyParts = nameParts.mapNotNull { it?.takeIf(String::isNotEmpty) } + return nonEmptyParts.drop(1).joinToString( + separator = "", + prefix = nonEmptyParts.firstOrNull().orEmpty(), + transform = String::capitalizeAsciiOnly, + ) +} + +private fun String.capitalizeAsciiOnly(): String { + if (isEmpty()) return this + val c = this[0] + return if (c in 'a'..'z') + c.uppercaseChar() + substring(1) + else + this +} + +internal inline fun SkieTarget.registerSkieTargetBasedTask( baseName: String, crossinline configurationAction: T.() -> Unit, ): TaskProvider { - val taskNameWithoutPrefix = skieLinkTaskName(baseName).removePrefix("skie") + val taskName = skieTargetBasedTaskName(baseName) - return project.registerSkieTask(taskNameWithoutPrefix, configurationAction) + return project.registerSkieTask(taskName, prefix = null, configurationAction = configurationAction) } internal inline fun Project.registerSkieTask( baseName: String, + prefix: String? = "skie", crossinline configurationAction: T.() -> Unit, ): TaskProvider { - val taskName = "skie${baseName.replaceFirstChar { it.uppercase() }}" + val taskName = lowerCamelCaseName(prefix, baseName) return tasks.register(taskName, T::class.java) { this.group = "skie" @@ -26,6 +110,3 @@ internal inline fun Project.registerSkieTask( this.configurationAction() } } - -internal fun KotlinNativeLink.skieLinkTaskName(baseName: String): String = - "skie${baseName.replaceFirstChar { it.uppercase() }}${this.name.removePrefix("link")}" diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/KotlinPluginExtensions.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/KotlinPluginExtensions.kt index cf384a09b..3716628b9 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/KotlinPluginExtensions.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/KotlinPluginExtensions.kt @@ -1,13 +1,13 @@ package co.touchlab.skie.plugin.util +import org.gradle.api.DomainObjectCollection +import org.gradle.api.NamedDomainObjectCollection import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.mpp.Framework import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget -internal val KotlinMultiplatformExtension.appleTargets: List - get() = targets - .mapNotNull { it as? KotlinNativeTarget } - .filter { it.konanTarget.family.isAppleFamily } +internal val KotlinMultiplatformExtension.appleTargets: NamedDomainObjectCollection + get() = targets.withType().matching { it.konanTarget.family.isAppleFamily } -internal val KotlinNativeTarget.frameworks: List - get() = binaries.filterIsInstance() +internal val KotlinNativeTarget.frameworks: DomainObjectCollection + get() = binaries.withType() diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/SkieTarget.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/SkieTarget.kt new file mode 100644 index 000000000..216154e90 --- /dev/null +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/SkieTarget.kt @@ -0,0 +1,174 @@ +package co.touchlab.skie.plugin.util + +import co.touchlab.skie.util.directory.SkieBuildDirectory +import co.touchlab.skie.util.directory.SkieDirectories +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.TaskProvider +import org.jetbrains.kotlin.gradle.dsl.* +import org.jetbrains.kotlin.gradle.plugin.SubpluginOption +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBinary +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind +import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.KotlinNativeLinkArtifactTask +import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink +import org.jetbrains.kotlin.gradle.utils.named +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.presetName +import org.jetbrains.kotlin.konan.util.visibleName +import java.io.File + +sealed interface SkieTarget { + val name: String + val project: Project + val task: TaskProvider + val konanTarget: KonanTarget + val buildType: NativeBuildType + + val skieDirectories: Provider + + val freeCompilerArgs: Provider> + + fun addPluginArgument(pluginId: String, option: SubpluginOption) + + fun addToCompilerClasspath(fileCollection: FileCollection) + + fun addFreeCompilerArgs(vararg args: String) + + class TargetBinary( + override val project: Project, + val target: KotlinNativeTarget, + val binary: NativeBinary, + ): SkieTarget { + override val konanTarget: KonanTarget = target.konanTarget + + override val buildType: NativeBuildType = binary.buildType + + override val name: String = "binary: ${binary.name}, target: ${target.targetName}, buildType: $buildType" + + override val task: TaskProvider = binary.linkTaskProvider + + override val skieDirectories = project.layout.buildDirectory.dir("skie/binaries/${binary.name}/$buildType/${binary.target.targetName}").map { + SkieDirectories(it.asFile) + } + + override val freeCompilerArgs: Provider> = task.map { + it.binary.freeCompilerArgs + } + + override fun addPluginArgument(pluginId: String, option: SubpluginOption) { + task.configure { + compilerPluginOptions.addPluginArgument( + pluginId, + option, + ) + } + } + + override fun addToCompilerClasspath(fileCollection: FileCollection) { + task.configure { + compilerPluginClasspath = listOfNotNull( + compilerPluginClasspath, + fileCollection, + ).reduce(FileCollection::plus) + } + } + + override fun addFreeCompilerArgs(vararg args: String) { + task.configure { + this.binary.freeCompilerArgs += args + } + } + } + + class Artifact( + override val project: Project, + val artifact: KotlinNativeArtifact, + override val konanTarget: KonanTarget, + override val buildType: NativeBuildType, + ): SkieTarget { + override val name: String = "artifact: ${artifact.artifactName}, target: $konanTarget, buildType: $buildType" + + override val task = project.tasks.named(linkTaskName(artifact, konanTarget, buildType)) + + override val skieDirectories = project.layout.buildDirectory.dir("skie/artifacts/${artifact.artifactName}/$buildType/$konanTarget").map { + SkieDirectories(it.asFile) + } + + override val freeCompilerArgs: Provider> = task.flatMap { + it.toolOptions.freeCompilerArgs + } + + override fun addPluginArgument(pluginId: String, option: SubpluginOption) { + task.configure { + toolOptions.freeCompilerArgs.addAll( + "-P", + "plugin:${pluginId}:${option.key}=${option.value}" + ) + } + } + + override fun addToCompilerClasspath(fileCollection: FileCollection) { + task.configure { + toolOptions.freeCompilerArgs.addAll( + fileCollection.files.map { it.canonicalPath }.sorted().map { "-Xplugin=$it" } + ) + } + } + + override fun addFreeCompilerArgs(vararg args: String) { + task.configure { + toolOptions.freeCompilerArgs.addAll( + *args + ) + } + } + + private companion object { + fun linkTaskName(artifact: KotlinNativeArtifact, konanTarget: KonanTarget, buildType: NativeBuildType): String { + return "assemble" + when (artifact) { + is KotlinNativeLibrary -> { + val kind = if (artifact.isStatic) NativeOutputKind.STATIC else NativeOutputKind.DYNAMIC + lowerCamelCaseName( + artifact.artifactName, + buildType.visibleName, + kind.taskNameClassifier, + "Library", + konanTarget.presetName, + ) + } + is KotlinNativeFramework -> lowerCamelCaseName( + artifact.artifactName, + buildType.visibleName, + NativeOutputKind.FRAMEWORK.taskNameClassifier, + konanTarget.presetName + ) + is KotlinNativeFatFramework -> lowerCamelCaseName( + artifact.artifactName, + buildType.visibleName, + NativeOutputKind.FRAMEWORK.taskNameClassifier, + konanTarget.presetName, + "ForFat", + ) + is KotlinNativeXCFramework -> lowerCamelCaseName( + artifact.artifactName, + buildType.visibleName, + NativeOutputKind.FRAMEWORK.taskNameClassifier, + konanTarget.presetName, + "ForXCF", + ) + else -> error("Unknown KotlinNativeArtifact type: $this") + } + } + } + } +} + +val SkieTarget.skieBuildDirectory: Provider + get() = skieDirectories.map { it.buildDirectory } + +val Provider.skieConfiguration: Provider + get() = map { it.skieConfiguration } diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/TaskDoOptimized.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/TaskDoOptimized.kt index dd5f2840e..702425f31 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/TaskDoOptimized.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/util/TaskDoOptimized.kt @@ -4,6 +4,7 @@ package co.touchlab.skie.plugin.util import org.gradle.api.Action import org.gradle.api.Task +import org.gradle.api.tasks.TaskProvider // We need to use an anonymous class instead of lambda to keep execution optimizations. // https://docs.gradle.org/7.4.2/userguide/validation_problems.html#implementation_unknown @@ -16,6 +17,11 @@ internal inline fun Task.doFirstOptimized(crossinline action: () -> Unit): Task }, ) +internal inline fun TaskProvider.configureDoFirstOptimized(crossinline action: () -> Unit) = + configure { + doFirstOptimized(action) + } + internal inline fun Task.doLastOptimized(crossinline action: () -> Unit): Task = doLast( object : Action { @@ -24,3 +30,8 @@ internal inline fun Task.doLastOptimized(crossinline action: () -> Unit): Task = } }, ) + +internal inline fun TaskProvider.configureDoLastOptimized(crossinline action: () -> Unit) = + configure { + doLastOptimized(action) + } diff --git a/common-gradle/gradle.properties b/common-gradle/gradle.properties index e002599af..47c8f0f72 100644 --- a/common-gradle/gradle.properties +++ b/common-gradle/gradle.properties @@ -13,5 +13,7 @@ versionSupport.gradleApi=7.3, 8.0, 8.1 touchlab.key=ABCDEFGHIJKLMNOPQRSTUVWXYZ +# This is here for dev-support +skieRuntimeVariantFallback=true kotlinNativeCompilerEmbeddableFromHome=false diff --git a/dev-support/skie/mac/framework/build.gradle.kts b/dev-support/skie/mac/framework/build.gradle.kts index c861e41fc..6dcf756a9 100644 --- a/dev-support/skie/mac/framework/build.gradle.kts +++ b/dev-support/skie/mac/framework/build.gradle.kts @@ -37,14 +37,14 @@ skie { } } +val exportedLibraries = listOf( + +) + kotlin { macosX64() macosArm64() - val exportedLibraries = listOf( - - ) - targets.withType { binaries { framework { @@ -99,3 +99,17 @@ tasks.register("dependenciesForExport") { } } } + +kotlinArtifacts { + Native.Framework("Kotlin") { + target = macosArm64 + isStatic = true + toolOptions { + freeCompilerArgs.add("-Xbinary=bundleId=Kotlin") + } + + exportedLibraries.forEach { + addModule(it) + } + } +} diff --git a/dev-support/skie/mac/swift/build.gradle.kts b/dev-support/skie/mac/swift/build.gradle.kts index 932fe6b59..df1517624 100644 --- a/dev-support/skie/mac/swift/build.gradle.kts +++ b/dev-support/skie/mac/swift/build.gradle.kts @@ -40,6 +40,7 @@ fun Exec.configureBuild(mode: String) { group = "build" val linkTask = tasks.getByPath(":skie:mac:framework:link${mode.capitalized()}Framework${architecture.kotlinGradleName.capitalized()}") +// val linkTask = tasks.getByPath(":skie:mac:framework:assembleKotlin${mode.capitalized()}Framework${architecture.kotlinGradleName.capitalized()}") // linkTask.enabled = false