As I’m working on my Swift language server, one of the things I need to do is to parse the Package.swift
file. There is a PackageDescription
library, but that’s unable for use within your own program if you are actually using SwiftPM.
Yeah…
So what are we to do? HACK IT UP!
Basically, we need to run this command:
$ swift -I /Library/Developer/Toolchains/swift-latest.xctoolchain/usr/lib/swift/pm \ -L /Library/Developer/Toolchains/swift-latest.xctoolchain/usr/lib/swift/pm \ -lPackageDescription Package.swift -fileno 1
Not really a big deal, just annoying.
Here’s the snippet to get the output:
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
// TODO(owensd): Need to actually get the version of Swift that the workspace is using based on the OS. | |
projectPath = params.rootPath! | |
let includePath = "/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/lib/swift/pm" | |
let packagePath = "\(projectPath!)/Package.swift" | |
let swiftPath = "/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swift" | |
let output = shell( | |
tool: swiftPath, | |
arguments: ["-I", includePath, "-L", includePath, "-lPackageDescription", packagePath, "-fileno", "1"]) | |
let packageJson = try JSValue.parse(output) | |
moduleName = packageJson["package"]["name"].string! |
Curious note: when you use string literal interpolation, even if your variable is an implicitly unwrapped optional, it will get output as an optional. Hence you see:
"\(projectPath!)/package.swift"
. Go figure.
Of course, the output is JSON. If you need a parser, you can use json-swift or any of the many others.
The shell
function is just a helper that I add to my SwiftFixes.swift
file:
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
public func shell(tool toolPath: String, arguments: [String]) -> String { | |
let process = Process() | |
process.launchPath = toolPath | |
process.arguments = arguments | |
let output = Pipe() | |
process.standardOutput = output | |
process.launch() | |
process.waitUntilExit() | |
return String( | |
data: output.fileHandleForReading.readDataToEndOfFile(), | |
encoding: .utf8)! | |
} |
Anyhow, if you too need to parse that pesky Package.swift
file, here you go.