Skip to content
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
14 changes: 14 additions & 0 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 36 additions & 14 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
// swift-tools-version:5.9
// swift-tools-version:6.0
import PackageDescription

let package = Package(
name: "RiveRuntime",
platforms: [.iOS("14.0"), .visionOS("1.0"), .tvOS("16.0"), .macOS("13.1"), .macCatalyst("14.0")],
products: [
.library(
name: "RiveRuntime",
targets: ["RiveRuntime"])],
targets: [
.binaryTarget(
name: "RiveRuntime",
url: "https://github.com/rive-app/rive-ios/releases/download/6.9.4/RiveRuntime.xcframework.zip",
checksum: "e5a5c810a838cf1ac8e44dcff606f84c1dbb80b17a144f6d7099b57705d83ee9"
)
]
name: "RiveRuntime",
platforms: [.iOS("14.0"), .visionOS("1.0"), .tvOS("16.0"), .macOS("13.1"), .macCatalyst("14.0")],
products: [
.library(
name: "RiveRuntime",
targets: ["RiveRuntime"]
),
.plugin(name: "RivePlugin", targets: ["RivePlugin"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.0"),
],
targets: [
.binaryTarget(
name: "RiveRuntime",
url: "https://github.com/rive-app/rive-ios/releases/download/6.9.4/RiveRuntime.xcframework.zip",
checksum: "e5a5c810a838cf1ac8e44dcff606f84c1dbb80b17a144f6d7099b57705d83ee9"
),
.executableTarget(
name: "rive-codegen",
dependencies: [
.target(name: "RiveRuntime"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
],
linkerSettings: [
.unsafeFlags(["-Xlinker", "-rpath", "-Xlinker", "@executable_path"]),
]
),
.plugin(
name: "RivePlugin",
capability: .buildTool(),
dependencies: ["rive-codegen"],
path: "Plugin"
),
]
)
57 changes: 57 additions & 0 deletions Plugin/BuildPlugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Foundation
import PackagePlugin

enum PluginError: Swift.Error, CustomStringConvertible, LocalizedError {
case incompatibleTarget(name: String)

var description: String {
switch self {
case let .incompatibleTarget(name): "Incompatible target called '\(name)'. Only Swift source targets can be used with the Rive plugin."
}
}

var errorDescription: String? { description }
}

@main
struct RivePlugin {
func createBuildCommands(
pluginWorkDirectory: URL,
tool: (String) throws -> PluginContext.Tool,
sourceFiles: FileList
) throws -> [Command] {
let outputDir = pluginWorkDirectory.appending(path: "GeneratedSources")
let inputFiles = sourceFiles.filter { $0.url.lastPathComponent.hasSuffix(".riv") }.map(\.url)

return try [
.buildCommand(
displayName: "Running rive-codegen",
executable: tool("rive-codegen").url,
arguments: ["generate"] + inputFiles.map { $0.absoluteString } + ["--output-directory", "\(outputDir)"],
environment: [:],
inputFiles: inputFiles,
outputFiles: [outputDir.appending(path: "Rive+Generated.swift")]
),
]
}
}

extension RivePlugin: BuildToolPlugin {
func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
guard let swiftTarget = target as? SwiftSourceModuleTarget else {
throw PluginError.incompatibleTarget(name: target.name)
}

return try createBuildCommands(pluginWorkDirectory: context.pluginWorkDirectoryURL, tool: context.tool, sourceFiles: swiftTarget.sourceFiles)
}
}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

extension RivePlugin: XcodeBuildToolPlugin {
func createBuildCommands(context: XcodePluginContext, target: XcodeTarget) throws -> [Command] {
try createBuildCommands(pluginWorkDirectory: context.pluginWorkDirectoryURL, tool: context.tool, sourceFiles: target.inputFiles)
}
}
#endif
62 changes: 62 additions & 0 deletions Sources/rive-codegen/Command.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import Foundation
import ArgumentParser

@main struct Command: AsyncParsableCommand {
static let configuration: CommandConfiguration = .init(
commandName: "rive-codegen",
abstract: "Generate Swift code for your Rive files",
subcommands: [GenerateCommand.self]
)
}

struct GenerateCommand: AsyncParsableCommand {
struct Options: ParsableArguments {
@Argument(help: "A list of Rive files to generate code for")
var inputFiles: [URL]
}

static let configuration: CommandConfiguration = .init(
commandName: "generate",
abstract: "Generate Swift code for your Rive files",
)

@OptionGroup var options: Options

@Option(
help:
"Output directory where the generated files are written. Warning: Replaces any existing files with the same filename."
) var outputDirectory: URL = .init(fileURLWithPath: FileManager.default.currentDirectoryPath)

@Flag(
name: .customLong("dry-run"),
help: "Simulate the command and print the operations, without actually affecting the file system."
) var isDryRun: Bool = false

func run() async throws {
let files = options.inputFiles

print(
"""
Swift Rive Code Generator is running with the following configuration:
- input files: \(files)
- Is dry run: \(isDryRun)
- Output directory: \(outputDirectory.path)
- Current directory: \(FileManager.default.currentDirectoryPath)
"""
)

let generator = Generator(isDryRun: isDryRun)

try await withThrowingTaskGroup(of: Void.self) { group in
for file in files {
group.addTask {
try await generator.load(file)
}
}

try await group.waitForAll()
}

try await generator.generate(outputDirectory: outputDirectory, as: "Rive+Generated.swift")
}
}
Loading