Skip to content

Alexander-Ignition/XSTooling

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🛠 XSTooling 🧰

Test SPM compatible Swift 5.3 GitHub license

Xcode and Swift toolset

Supported tools:

  • shell
  • xcrun
  • simstl

Getting Started

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

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 the ProcessCommand with additional arguments
let sh = Shell.default
sh.command // ProcessCommand
sh.command.environment // [String: String]?
sh.command.currentDirectoryURL // URL?
sh("ls") // ProcessCommand

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()

simctl

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()

License

MIT