Skip to content

Declare custom Package.swift template and its properties #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: next-release
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions api/multiplatform-swiftpackage.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ public final class com/chromaticnoise/multiplatformswiftpackage/MultiplatformSwi
}

public class com/chromaticnoise/multiplatformswiftpackage/SwiftPackageExtension {
public static final field Companion Lcom/chromaticnoise/multiplatformswiftpackage/SwiftPackageExtension$Companion;
public fun <init> (Lorg/gradle/api/Project;)V
public final fun buildConfiguration (Lorg/gradle/api/Action;)V
public final fun distributionMode (Lorg/gradle/api/Action;)V
public final fun outputDirectory (Ljava/io/File;)V
public final fun packageName (Ljava/lang/String;)V
public final fun packageTemplate (Lgroovy/lang/Closure;)V
public final fun packageTemplate (Ljava/io/File;)V
public final fun packageTemplate (Ljava/io/File;Lgroovy/lang/Closure;)V
public final fun packageTemplate (Ljava/io/File;Lkotlin/jvm/functions/Function1;)V
public final fun packageTemplate (Lkotlin/jvm/functions/Function1;)V
public final fun swiftToolsVersion (Ljava/lang/String;)V
public final fun targetPlatforms (Lorg/gradle/api/Action;)V
}
Expand All @@ -28,6 +34,58 @@ public final class com/chromaticnoise/multiplatformswiftpackage/dsl/Distribution
public final fun remote (Ljava/lang/String;)V
}

public final class com/chromaticnoise/multiplatformswiftpackage/dsl/PackageTemplateDSL {
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/util/Collection;
public final fun component4 ()Lcom/chromaticnoise/multiplatformswiftpackage/dsl/RemoteDistribution;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/util/Collection;Lcom/chromaticnoise/multiplatformswiftpackage/dsl/RemoteDistribution;Ljava/util/Map;)Lcom/chromaticnoise/multiplatformswiftpackage/dsl/PackageTemplateDSL;
public static synthetic fun copy$default (Lcom/chromaticnoise/multiplatformswiftpackage/dsl/PackageTemplateDSL;Ljava/lang/String;Ljava/lang/String;Ljava/util/Collection;Lcom/chromaticnoise/multiplatformswiftpackage/dsl/RemoteDistribution;Ljava/util/Map;ILjava/lang/Object;)Lcom/chromaticnoise/multiplatformswiftpackage/dsl/PackageTemplateDSL;
public fun equals (Ljava/lang/Object;)Z
public final fun get (Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;)Ljava/lang/Object;
public final fun get (Ljava/lang/String;)Ljava/lang/Object;
public final fun getPackageName ()Ljava/lang/String;
public final fun getPlatforms ()Ljava/util/Collection;
public final fun getRemoteDistribution ()Lcom/chromaticnoise/multiplatformswiftpackage/dsl/RemoteDistribution;
public final fun getToolsVersion ()Ljava/lang/String;
public fun hashCode ()I
public final fun set (Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;Ljava/lang/Object;)V
public final fun set (Ljava/lang/String;Ljava/lang/Object;)V
public final fun setPackageName (Ljava/lang/String;)V
public final fun setPlatforms (Ljava/util/Collection;)V
public final fun setRemoteDistribution (Lcom/chromaticnoise/multiplatformswiftpackage/dsl/RemoteDistribution;)V
public final fun setToolsVersion (Ljava/lang/String;)V
public fun toString ()Ljava/lang/String;
}

public final class com/chromaticnoise/multiplatformswiftpackage/dsl/Platform {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lcom/chromaticnoise/multiplatformswiftpackage/dsl/Platform;
public static synthetic fun copy$default (Lcom/chromaticnoise/multiplatformswiftpackage/dsl/Platform;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/chromaticnoise/multiplatformswiftpackage/dsl/Platform;
public fun equals (Ljava/lang/Object;)Z
public final fun getName ()Ljava/lang/String;
public final fun getVersion ()Ljava/lang/String;
public fun hashCode ()I
public final fun setName (Ljava/lang/String;)V
public final fun setVersion (Ljava/lang/String;)V
public fun toString ()Ljava/lang/String;
}

public final class com/chromaticnoise/multiplatformswiftpackage/dsl/RemoteDistribution {
public fun equals (Ljava/lang/Object;)Z
public final fun getBaseUrl ()Ljava/lang/String;
public final fun getFullUrl ()Ljava/lang/String;
public final fun getZipFileChecksum ()Ljava/lang/String;
public final fun getZipFileName ()Ljava/lang/String;
public fun hashCode ()I
public final fun setBaseUrl (Ljava/lang/String;)V
public final fun setZipFileChecksum (Ljava/lang/String;)V
public final fun setZipFileName (Ljava/lang/String;)V
public fun toString ()Ljava/lang/String;
}

public final class com/chromaticnoise/multiplatformswiftpackage/dsl/TargetPlatformDsl {
public fun <init> ()V
public final fun iOS (Lorg/gradle/api/Action;)V
Expand All @@ -42,3 +100,14 @@ public final class com/chromaticnoise/multiplatformswiftpackage/dsl/TargetPlatfo
public final fun v (Ljava/lang/String;)V
}

public final class com/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey : java/lang/Enum {
public static final field Checksum Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;
public static final field IsLocal Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;
public static final field Name Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;
public static final field Platforms Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;
public static final field ToolsVersion Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;
public static final field Url Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;
public static fun valueOf (Ljava/lang/String;)Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;
public static fun values ()[Lcom/chromaticnoise/multiplatformswiftpackage/dsl/TemplateKey;
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ package com.chromaticnoise.multiplatformswiftpackage

import com.chromaticnoise.multiplatformswiftpackage.domain.*
import com.chromaticnoise.multiplatformswiftpackage.domain.PluginConfiguration.PluginConfigurationError
import com.chromaticnoise.multiplatformswiftpackage.domain.SwiftPackageTemplate.TemplateFile
import com.chromaticnoise.multiplatformswiftpackage.dsl.BuildConfigurationDSL
import com.chromaticnoise.multiplatformswiftpackage.dsl.DistributionModeDSL
import com.chromaticnoise.multiplatformswiftpackage.dsl.PackageTemplateDSL
import com.chromaticnoise.multiplatformswiftpackage.dsl.TargetPlatformDsl
import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.util.ConfigureUtil
import java.io.File

public open class SwiftPackageExtension(project: Project) {
Expand All @@ -18,6 +22,7 @@ public open class SwiftPackageExtension(project: Project) {
internal var distributionMode: DistributionMode = DistributionMode.Local
internal var targetPlatforms: Collection<Either<List<PluginConfigurationError>, TargetPlatform>> = emptyList()
internal var appleTargets: Collection<AppleTarget> = emptyList()
internal var packageTemplate: SwiftPackageTemplate = SwiftPackageTemplate(file = DEFAULT_TEMPLATE_FILE, configure = {})

/**
* Sets the name of the Swift package.
Expand Down Expand Up @@ -73,4 +78,38 @@ public open class SwiftPackageExtension(project: Project) {
targetPlatforms = dsl.targetPlatforms
}
}

/**
* Builder for the [SwiftPackageTemplate].
*
* @param path that points to the template file.
* @param configure closure that configures the properties of the template.
*/
public fun packageTemplate(path: File, configure: PackageTemplateDSL.() -> Unit) {
packageTemplate = SwiftPackageTemplate(
file = TemplateFile.File(path),
configure = configure
)
}

public fun packageTemplate(path: File, configure: Closure<PackageTemplateDSL>) {
packageTemplate(path) { ConfigureUtil.configure(configure, this) }
}

public fun packageTemplate(path: File) {
packageTemplate(path) {}
}

public fun packageTemplate(configure: PackageTemplateDSL.() -> Unit) {
packageTemplate = SwiftPackageTemplate(DEFAULT_TEMPLATE_FILE, configure)
}

public fun packageTemplate(configure: Closure<PackageTemplateDSL>) {
packageTemplate = SwiftPackageTemplate(DEFAULT_TEMPLATE_FILE) { ConfigureUtil.configure(configure, this) }
}

private companion object {
private val DEFAULT_TEMPLATE_FILE =
TemplateFile.Resource(MultiplatformSwiftPackagePlugin::class.java.getResource("/templates/Package.swift.template"))
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package com.chromaticnoise.multiplatformswiftpackage.domain

internal data class DistributionURL(val value: String) {
private val slashTerminatedValue: String get() =
value.takeIf { it.endsWith("/") } ?:
"$value/"

fun appendPath(path: String) = DistributionURL("$slashTerminatedValue$path")
fun appendPath(path: String) = DistributionURL("${slashTerminatedUrl(value)}$path")
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ internal class PluginConfiguration private constructor(
val swiftToolsVersion: SwiftToolVersion,
val distributionMode: DistributionMode,
val targetPlatforms: Collection<TargetPlatform>,
val appleTargets: Collection<AppleTarget>
val appleTargets: Collection<AppleTarget>,
val packageTemplate: SwiftPackageTemplate
) {
internal companion object {
fun of(extension: SwiftPackageExtension): Either<List<PluginConfigurationError>, PluginConfiguration> {
Expand Down Expand Up @@ -47,7 +48,8 @@ internal class PluginConfiguration private constructor(
extension.swiftToolsVersion!!,
extension.distributionMode,
targetPlatforms,
extension.appleTargets
extension.appleTargets,
extension.packageTemplate
)
)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,66 @@
package com.chromaticnoise.multiplatformswiftpackage.domain

import com.chromaticnoise.multiplatformswiftpackage.MultiplatformSwiftPackagePlugin
import com.chromaticnoise.multiplatformswiftpackage.domain.SwiftPackageTemplate.TemplateFile
import com.chromaticnoise.multiplatformswiftpackage.dsl.PackageTemplateDSL
import com.chromaticnoise.multiplatformswiftpackage.dsl.Platform
import com.chromaticnoise.multiplatformswiftpackage.dsl.RemoteDistribution
import com.chromaticnoise.multiplatformswiftpackage.dsl.TemplateKey
import com.chromaticnoise.multiplatformswiftpackage.dsl.TemplateKey.*
import com.chromaticnoise.multiplatformswiftpackage.task.zipFileChecksum
import com.chromaticnoise.multiplatformswiftpackage.task.zipFileName
import org.gradle.api.Project

internal data class SwiftPackageConfiguration(
private val project: Project,
private val packageTemplate: SwiftPackageTemplate,
private val toolsVersion: SwiftToolVersion,
private val packageName: PackageName,
private val toolVersion: SwiftToolVersion,
private val platforms: String,
private val distributionMode: DistributionMode,
private val zipChecksum: String
private val outputDirectory: OutputDirectory,
private val targetPlatforms: Collection<TargetPlatform>,
private val appleTargets: Collection<AppleTarget>
) {

private val distributionUrl = when (distributionMode) {
DistributionMode.Local -> null
is DistributionMode.Remote -> distributionMode.url.appendPath(zipFileName(project, packageName))
internal val templateFile: TemplateFile get() = packageTemplate.file

internal val templateProperties: Map<String, Any?> get() = PackageTemplateDSL(
toolsVersion = toolsVersion.name,
packageName = packageName.value,
platforms = platforms,
remoteDistribution = remoteDistribution
).run {
packageTemplate.configure(this)
mapOf(
ToolsVersion to toolsVersion,
Name to packageName,
Platforms to platforms.joinToString(",\n") { ".${it.name}(.v${it.version})" },
IsLocal to (remoteDistribution == null),
Url to remoteDistribution?.fullUrl,
Checksum to remoteDistribution?.zipFileChecksum
)
.withStringKeys()
.apply { putAll(extraProperties) }
}

private val remoteDistribution get() = (distributionMode as? DistributionMode.Remote)?.let { mode ->
RemoteDistribution(
baseUrl = mode.url.value,
zipFileName = zipFileName(project, packageName),
zipFileChecksum = zipFileChecksum(project, outputDirectory, packageName).trim()
)
}

internal val templateProperties = mapOf(
"toolsVersion" to toolVersion.name,
"name" to packageName.value,
"platforms" to platforms,
"isLocal" to (distributionMode == DistributionMode.Local),
"url" to distributionUrl?.value,
"checksum" to zipChecksum.trim()
)
private val platforms: MutableCollection<Platform> get() = targetPlatforms.flatMap { platform ->
appleTargets
.filter { appleTarget -> platform.targets.firstOrNull { it.konanTarget == appleTarget.nativeTarget.konanTarget } != null }
.mapNotNull { target -> target.nativeTarget.konanTarget.family.swiftPackagePlatformName }
.distinct()
.map { platformName -> Platform(platformName, platform.version.name) }
}.toMutableList()

private fun Map<TemplateKey, Any?>.withStringKeys(): MutableMap<String, Any?> = mapKeys { it.key.value }.toMutableMap()

internal companion object {
internal const val FILE_NAME = "Package.swift"

internal val templateFile =
MultiplatformSwiftPackagePlugin::class.java.getResource("/templates/Package.swift.template")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.chromaticnoise.multiplatformswiftpackage.domain

import com.chromaticnoise.multiplatformswiftpackage.dsl.PackageTemplateDSL
import java.net.URL

internal data class SwiftPackageTemplate(
val file: TemplateFile,
val configure: PackageTemplateDSL.() -> Unit
) {

internal sealed class TemplateFile {
data class Resource(val url: URL) : TemplateFile()
data class File(val value: java.io.File) : TemplateFile()
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package com.chromaticnoise.multiplatformswiftpackage.domain

internal fun <T> String.ifNotBlank(f: (String) -> T?): T? = takeIf { it.isNotBlank() }?.let { f(it) }

internal fun slashTerminatedUrl(url: String): String = url.takeIf { it.endsWith("/") } ?: "$url/"
Loading