Created
April 19, 2017 12:40
-
-
Save Grayson/0512824a6dae381a3ff6ab797f88d95d to your computer and use it in GitHub Desktop.
Prototypical swift script to build dependencies in Package.swift
This file contains hidden or 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
#!/usr/bin/swift | |
import Foundation | |
struct Project { | |
let name: String | |
let path: URL | |
let url: URL | |
let version: String | |
let dependencies: [Project] | |
static func from(_ dict: [String: Any]) -> Project? { | |
guard | |
let name = dict["name"] as? String, | |
let pathString = dict["path"] as? String, | |
let urlString = dict["url"] as? String, | |
let url = URL(string: urlString), | |
let version = dict["version"] as? String, | |
let dependenciesDictArray = dict["dependencies"] as? [[String: Any]] | |
else { return nil } | |
let path = URL(fileURLWithPath: pathString) | |
let dependencies = dependenciesDictArray.flatMap(Project.from) | |
return Project(name: name, path: path, url: url, version: version, dependencies: dependencies) | |
} | |
} | |
extension String { | |
func trim() -> String { | |
return self.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines) | |
} | |
} | |
@discardableResult | |
func sh(_ command: String, _ args: [String] = [], _ wd: URL? = nil) -> String { | |
let process = Process() | |
process.launchPath = command | |
process.arguments = args | |
if let wd = wd { process.currentDirectoryPath = wd.path } | |
let standardOut = Pipe() | |
process.standardOutput = standardOut | |
process.launch() | |
let result = String(data: standardOut.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? "" | |
process.waitUntilExit() | |
return result | |
} | |
func scriptPath() -> URL { | |
let scriptRelPath = ProcessInfo.processInfo.arguments.drop { $0 != "-interpret" }.dropFirst().first! | |
return URL(string: scriptRelPath, relativeTo: URL(fileURLWithPath: ProcessInfo.processInfo.environment["PWD"]!))!.absoluteURL | |
} | |
func which(_ command: String) -> String { | |
return sh("/bin/sh", ["-c", "which \(command)"]).trim() | |
} | |
let swiftPath = which("swift") | |
let lnPath = which("ln") | |
let mkdirPath = which("mkdir") | |
func recursivelySymlinkDependencies(from: Project, into: URL, fileManager: FileManager = FileManager.default) { | |
from.dependencies.forEach { project in | |
let destination = into.appendingPathComponent(project.name) | |
if fileManager.fileExists(atPath: destination.path) { return } | |
print("Symlinking: \(project.name) into \(destination.path)") | |
sh(lnPath, ["-s", project.path.path, destination.path]) | |
} | |
} | |
func buildDependencies(from: Project, fileManager: FileManager = FileManager.default) { | |
from.dependencies.forEach { project in | |
if !fileManager.fileExists(atPath: project.path.path) { return } | |
for config in ["debug", "release"] { | |
print("Building: \(project.name) (\(config))") | |
sh(swiftPath, ["build", "-c", config, "--build-path", "./build"], project.path) | |
} | |
} | |
} | |
func main() { | |
let rootPath = URL(string: "../", relativeTo: scriptPath())!.absoluteURL | |
let packageDirectory = rootPath.deletingLastPathComponent() | |
sh(swiftPath, ["package", "fetch"], packageDirectory) | |
let dependencyJsonString = sh(swiftPath, ["package", "show-dependencies", "--format", "json"], rootPath) | |
guard | |
let dependencyJsonData = dependencyJsonString.data(using: .utf8), | |
let dependencyJson = try? JSONSerialization.jsonObject(with: dependencyJsonData, options: []), | |
let jsonDict = dependencyJson as? [String: Any], | |
let project = Project.from(jsonDict) | |
else { | |
print("Unable to get dependency graph data.") | |
exit(-1) | |
} | |
let dependenciesPath = rootPath.appendingPathComponent("Packages") | |
if (!FileManager.default.fileExists(atPath: dependenciesPath.path)) { | |
print("Creating \(dependenciesPath)") | |
sh(mkdirPath, ["-p", dependenciesPath.path]) | |
} | |
recursivelySymlinkDependencies(from: project, into: dependenciesPath) | |
buildDependencies(from: project) | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment