-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Alternative approach - using a command plugin
- Loading branch information
Showing
4 changed files
with
179 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import Foundation | ||
|
||
/// Basic implementation of a config file parser. | ||
/// This probably exists somewhere already! | ||
class GodotConfigFile { | ||
static let sectionPattern: Regex = #/\s*\[(?<section>\w+)\]\s*/# | ||
static let assignmentPattern: Regex = #/\s*(?<key>\S+)\s*=\s*(?<value>.*)\s*/# | ||
static let stringPattern: Regex = #/"(?<content>.*)"/# | ||
|
||
var content: [String: [String: String]] | ||
var sections: [String] | ||
var _encoded: String? | ||
|
||
init(_ url: URL) async throws { | ||
var section = "_" | ||
var values: [String: String] = [:] | ||
var content: [String: [String: String]] = [:] | ||
var sections: [String] = [] | ||
|
||
func endSection() { | ||
if !values.isEmpty { | ||
sections.append(section) | ||
content[section] = values | ||
} | ||
} | ||
|
||
for try await line in url.lines { | ||
if let match = line.matches(of: Self.sectionPattern).first { | ||
endSection() | ||
section = String(match.section) | ||
values = [:] | ||
} else if let match = line.matches(of: Self.assignmentPattern).first { | ||
values[String(match.key)] = String(match.value) | ||
} | ||
} | ||
endSection() | ||
|
||
self.content = content | ||
self.sections = sections | ||
} | ||
|
||
/// Set a string value in a section. | ||
func set(_ key: String, _ value: String, section: String) { | ||
if content[section] == nil { | ||
content[section] = [:] | ||
} | ||
content[section]?[key] = "\"\(value)\"" | ||
_encoded = nil | ||
} | ||
|
||
/// Get a string value from a section. | ||
func get(_ key: String, section: String) -> String? { | ||
if let entry = content[section]?[key], | ||
let value = entry.matches(of: Self.stringPattern).first | ||
{ | ||
return String(value.content) | ||
} | ||
return nil | ||
} | ||
|
||
/// Remove a section. | ||
func remove(section: String) { | ||
content.removeValue(forKey: section) | ||
_encoded = nil | ||
} | ||
|
||
/// The string-encoded version of the file. | ||
var encoded: String { | ||
if _encoded == nil { | ||
var output = "" | ||
for (section, values) in content { | ||
output.append("[\(section)]\n") | ||
for (key, value) in values { | ||
output.append("\(key) = \(value)\n") | ||
} | ||
} | ||
_encoded = output | ||
} | ||
|
||
return _encoded! | ||
} | ||
|
||
/// Write the file to a URL as a UTF8 string. | ||
func write(to url: URL) async throws { | ||
try encoded.write(to: url, atomically: true, encoding: .utf8) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- | ||
// Created by Sam Deane on 16/10/24. | ||
// All code (c) 2024 - present day, Elegant Chaos Limited. | ||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- | ||
|
||
import Foundation | ||
import PackagePlugin | ||
|
||
/// Takes `.gdswift` files and generates `.gdextension` files from them. | ||
@main struct ExtensionBuilderCommandPlugin: CommandPlugin { | ||
func performCommand(context: PluginContext, arguments: [String]) async throws { | ||
// Extract the target arguments (if there are none, we assume all). | ||
var argExtractor = ArgumentExtractor(arguments) | ||
let targetNames = argExtractor.extractOption(named: "target") | ||
let targets = | ||
targetNames.isEmpty | ||
? context.package.targets | ||
: try context.package.targets(named: targetNames) | ||
|
||
let builder = try context.tool(named: "ExtensionBuilder").path | ||
|
||
// Iterate over the targets we've been asked to format. | ||
for target in targets { | ||
// Skip any type of target that doesn't have source files. | ||
// Note: We could choose to instead emit a warning or error here. | ||
guard let target = target.sourceModule else { continue } | ||
|
||
let inputFiles = target.sourceFiles.filter({ $0.path.extension == "gdswift" }).map { $0.path } | ||
if inputFiles.isEmpty { | ||
Diagnostics.warning("No .gdswift files found for \(target.name).") | ||
continue | ||
} | ||
|
||
let settings = try await GodotConfigFile(URL(fileURLWithPath: inputFiles.first!.string)) | ||
let result = try packageManager.build( | ||
.target(target.name), | ||
parameters: .init(configuration: .debug, logging: .concise, echoLogs: true) | ||
) | ||
if result.succeeded { | ||
for artifact in result.builtArtifacts.filter({ $0.kind != .executable }) { | ||
settings.set("macos.debug", artifact.path.string, section: "libraries") | ||
settings.set("macos.release", artifact.path.string.replacing("debug", with: "release"), section: "libraries") | ||
} | ||
} else { | ||
Diagnostics.warning("Couldn't build \(target.name).") | ||
} | ||
|
||
let url = URL(fileURLWithPath: context.package.directory.appending("\(target.name).gdextension").string) | ||
try await settings.write(to: url) | ||
// var arguments = [context.package.directory, target.directory, context.package.directory] | ||
// arguments.append(contentsOf: inputFiles) | ||
// print(arguments) | ||
|
||
// // Invoke `sometool` on the target directory, passing a configuration | ||
// // file from the package directory. | ||
// let sometoolExec = URL(fileURLWithPath: builder.string) | ||
// let process = try Process.run(sometoolExec, arguments: arguments.map { $0.string }) | ||
// process.waitUntilExit() | ||
|
||
// // Check whether the subprocess invocation was successful. | ||
// if process.terminationReason == .exit && process.terminationStatus == 0 { | ||
// print("Exported gdextension file for \(target.name).") | ||
// } else { | ||
// let problem = "\(process.terminationReason):\(process.terminationStatus)" | ||
// Diagnostics.error("Exported gdextension failed: \(problem)") | ||
// } | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters