Xcode and Swift toolset
Supported tools:
- shell
- xcrun
- simstl
To use the XSTooling
library in a SwiftPM project, add the following line to the dependencies in your Package.swift
file:
.package(url: "https://github.com/Alexander-Ignition/XSTooling", from: "0.0.2"),
Include "XSTooling"
as a dependency for your executable target:
.target(name: "<target>", dependencies: [
"XSTooling",
]),
Finally, add import XSTooling
to your source code.
import XSTooling
let sh = Shell.default
try await sh("swift build").run()
Shell command can be run
or read
.
Read the shell command output.
let version = try await sh("xcodebuild -version").read().string
Run shell command with redirection to stdout and stderr.
try await sh("ls -al").run()
Redirection can be configured, for example, to write to a log file.
let url = URL(fileURLWithPath: "logs.txt", isDirectory: false)
FileManager.default.createFile(atPath: url.path, contents: nil)
let file = try FileHandle(forWritingTo: url)
try await sh("swift build").run(.output(file).error(file))
Shell
has predefined instances.
Shell.default
Shell.sh
Shell.bash
Shell.zsh
Conceptually, a Shell
is a wrapper over a ProcessCommand
.
sh.command
contains common parameters for all commands.sh("ls")
each call to this method returned a copy of theProcessCommand
with additional arguments
let sh = Shell.default
sh.command // ProcessCommand
sh.command.environment // [String: String]?
sh.command.currentDirectoryURL // URL?
sh("ls") // ProcessCommand
The main component is ProcessCommand
. Which can configure and run a subprocess. The read
and run
methods are called on the ProcessCommand
.
let command = ProcessCommand(
path: "/usr/bin/xcodebuild",
arguments: ["-version"]
)
try await command.run()
The location of the executable file is not always known. To do this, there is a find
method that searches for an executable file by name.
try await ProcessCommand
.find("xcodebuild")!
.appending(argument: "-version")
.run()
By analogy with Shell, you can make other wrappers over the ProcessCommand
Simctl
(Simulator control tool) is an example of a complex such wrapper
Using simctl, you can search for iPhone 12, turn it on and launch the application.
let xcrun = XCRun()
let simulator = xcrun.simctl
let list = try await simulator.list(.devices, "iPhone 12", available: true).json.decode()
let devices = list.devices.flatMap { $0.value }
for info in devices where info.state == "Booted" {
try await simulator.device(info.udid).shutdown.run()
}
let udid = devices.first!.udid
try await simulator.device(udid).boot.run()
try await simulator.device(udid).app("com.example.app").launch.run()
MIT