Fixed paths and formatting

This commit is contained in:
fedor
2024-01-22 14:57:24 -05:00
parent a5572bd3da
commit c94de82123
6 changed files with 248 additions and 248 deletions
+2 -2
View File
@@ -60,9 +60,9 @@ task:
macos_instance: macos_instance:
image: ghcr.io/cirruslabs/macos-sonoma-xcode:$XCODE_TAG image: ghcr.io/cirruslabs/macos-sonoma-xcode:$XCODE_TAG
build_script: swift build --arch $BUILD_ARCH --product tart build_script: swift build --arch $BUILD_ARCH --product tart
sign_script: codesign --sign - --entitlements Resources/tart-dev.entitlements --force .build/$BUILD_ARCH-apple-macosx/tart sign_script: codesign --sign - --entitlements Resources/tart-dev.entitlements --force .build/$BUILD_ARCH-apple-macosx/debug/tart
binary_artifacts: binary_artifacts:
path: .build/$BUILD_ARCH-apple-macosx/tart path: .build/$BUILD_ARCH-apple-macosx/debug/tart
task: task:
only_if: $CIRRUS_TAG == '' && ($CIRRUS_USER_PERMISSION == 'write' || $CIRRUS_USER_PERMISSION == 'admin') only_if: $CIRRUS_TAG == '' && ($CIRRUS_USER_PERMISSION == 'write' || $CIRRUS_USER_PERMISSION == 'admin')
+18 -18
View File
@@ -24,9 +24,9 @@ struct Create: AsyncParsableCommand {
throw ValidationError("Please specify either a --from-ipsw or --linux option!") throw ValidationError("Please specify either a --from-ipsw or --linux option!")
} }
#if arch(x86_64) #if arch(x86_64)
if fromIPSW != nil { if fromIPSW != nil {
throw ValidationError("Only Linux VMs are supported on Intel!") throw ValidationError("Only Linux VMs are supported on Intel!")
} }
#endif #endif
} }
@@ -39,27 +39,27 @@ struct Create: AsyncParsableCommand {
try await withTaskCancellationHandler(operation: { try await withTaskCancellationHandler(operation: {
#if arch(arm64) #if arch(arm64)
if let fromIPSW = fromIPSW { if let fromIPSW = fromIPSW {
let ipswURL: URL let ipswURL: URL
if fromIPSW == "latest" { if fromIPSW == "latest" {
defaultLogger.appendNewLine("Looking up the latest supported IPSW...") defaultLogger.appendNewLine("Looking up the latest supported IPSW...")
let image = try await withCheckedThrowingContinuation { continuation in let image = try await withCheckedThrowingContinuation { continuation in
VZMacOSRestoreImage.fetchLatestSupported() { result in VZMacOSRestoreImage.fetchLatestSupported() { result in
continuation.resume(with: result) continuation.resume(with: result)
}
} }
ipswURL = image.url
} else if fromIPSW.starts(with: "http://") || fromIPSW.starts(with: "https://") {
ipswURL = URL(string: fromIPSW)!
} else {
ipswURL = URL(fileURLWithPath: NSString(string: fromIPSW).expandingTildeInPath)
} }
ipswURL = image.url _ = try await VM(vmDir: tmpVMDir, ipswURL: ipswURL, diskSizeGB: diskSize)
} else if fromIPSW.starts(with: "http://") || fromIPSW.starts(with: "https://") {
ipswURL = URL(string: fromIPSW)!
} else {
ipswURL = URL(fileURLWithPath: NSString(string: fromIPSW).expandingTildeInPath)
} }
_ = try await VM(vmDir: tmpVMDir, ipswURL: ipswURL, diskSizeGB: diskSize)
}
#endif #endif
if linux { if linux {
+43 -43
View File
@@ -37,23 +37,23 @@ struct Run: AsyncParsableCommand {
var graphics: Bool = false var graphics: Bool = false
#if arch(arm64) #if arch(arm64)
@Flag(help: "Boot into recovery mode") @Flag(help: "Boot into recovery mode")
#endif #endif
var recovery: Bool = false var recovery: Bool = false
#if arch(arm64) #if arch(arm64)
@Flag(help: ArgumentHelp( @Flag(help: ArgumentHelp(
"Use screen sharing instead of the built-in UI.", "Use screen sharing instead of the built-in UI.",
discussion: "Useful since Screen Sharing supports copy/paste, drag and drop, etc.\n" discussion: "Useful since Screen Sharing supports copy/paste, drag and drop, etc.\n"
+ "Note that Remote Login option should be enabled inside the VM.")) + "Note that Remote Login option should be enabled inside the VM."))
#endif #endif
var vnc: Bool = false var vnc: Bool = false
#if arch(arm64) #if arch(arm64)
@Flag(help: ArgumentHelp( @Flag(help: ArgumentHelp(
"Use Virtualization.Framework's VNC server instead of the build-in UI.", "Use Virtualization.Framework's VNC server instead of the build-in UI.",
discussion: "Useful since this type of VNC is available in recovery mode and in macOS installation.\n" discussion: "Useful since this type of VNC is available in recovery mode and in macOS installation.\n"
+ "Note that this feature is experimental and there may be bugs present when using VNC.")) + "Note that this feature is experimental and there may be bugs present when using VNC."))
#endif #endif
var vncExperimental: Bool = false var vncExperimental: Bool = false
@@ -73,18 +73,18 @@ struct Run: AsyncParsableCommand {
var disk: [String] = [] var disk: [String] = []
#if arch(arm64) #if arch(arm64)
@Option(name: [.customLong("rosetta")], help: ArgumentHelp( @Option(name: [.customLong("rosetta")], help: ArgumentHelp(
"Attaches a Rosetta share to the guest Linux VM with a specific tag (e.g. --rosetta=\"rosetta\")", "Attaches a Rosetta share to the guest Linux VM with a specific tag (e.g. --rosetta=\"rosetta\")",
discussion: """ discussion: """
Requires host to be macOS 13.0 (Ventura) with Rosetta installed. The latter can be done Requires host to be macOS 13.0 (Ventura) with Rosetta installed. The latter can be done
by running "softwareupdate --install-rosetta" (without quotes) in the Terminal.app. by running "softwareupdate --install-rosetta" (without quotes) in the Terminal.app.
Note that you also have to configure Rosetta in the guest Linux VM by following the Note that you also have to configure Rosetta in the guest Linux VM by following the
steps from "Mount the Shared Directory and Register Rosetta" section here: steps from "Mount the Shared Directory and Register Rosetta" section here:
https://developer.apple.com/documentation/virtualization/running_intel_binaries_in_linux_vms_with_rosetta#3978496 https://developer.apple.com/documentation/virtualization/running_intel_binaries_in_linux_vms_with_rosetta#3978496
""", """,
valueName: "tag" valueName: "tag"
)) ))
#endif #endif
var rosettaTag: String? var rosettaTag: String?
@@ -114,13 +114,13 @@ struct Run: AsyncParsableCommand {
var netSoftnet: Bool = false var netSoftnet: Bool = false
#if arch(arm64) #if arch(arm64)
@Flag(help: ArgumentHelp("Disables audio and entropy devices and switches to only Mac-specific input devices.", discussion: "Useful for running a VM that can be suspended via \"tart suspend\".")) @Flag(help: ArgumentHelp("Disables audio and entropy devices and switches to only Mac-specific input devices.", discussion: "Useful for running a VM that can be suspended via \"tart suspend\"."))
#endif #endif
var suspendable: Bool = false var suspendable: Bool = false
#if arch(arm64) #if arch(arm64)
@Flag(help: ArgumentHelp("Whether system hot keys should be sent to the guest instead of the host", @Flag(help: ArgumentHelp("Whether system hot keys should be sent to the guest instead of the host",
discussion: "If enabled then system hot keys like Cmd+Tab will be sent to the guest instead of the host.")) discussion: "If enabled then system hot keys like Cmd+Tab will be sent to the guest instead of the host."))
#endif #endif
var captureSystemKeys: Bool = false var captureSystemKeys: Bool = false
@@ -249,15 +249,15 @@ struct Run: AsyncParsableCommand {
var resume = false var resume = false
#if arch(arm64) #if arch(arm64)
if #available(macOS 14, *) { if #available(macOS 14, *) {
if FileManager.default.fileExists(atPath: vmDir.stateURL.path) { if FileManager.default.fileExists(atPath: vmDir.stateURL.path) {
print("restoring VM state from a snapshot...") print("restoring VM state from a snapshot...")
try await vm!.virtualMachine.restoreMachineStateFrom(url: vmDir.stateURL) try await vm!.virtualMachine.restoreMachineStateFrom(url: vmDir.stateURL)
try FileManager.default.removeItem(at: vmDir.stateURL) try FileManager.default.removeItem(at: vmDir.stateURL)
resume = true resume = true
print("resuming VM...") print("resuming VM...")
}
} }
}
#endif #endif
try await vm!.start(recovery: recovery, resume: resume) try await vm!.start(recovery: recovery, resume: resume)
@@ -305,23 +305,23 @@ struct Run: AsyncParsableCommand {
Task { Task {
do { do {
#if arch(arm64) #if arch(arm64)
if #available(macOS 14, *) { if #available(macOS 14, *) {
try vm!.configuration.validateSaveRestoreSupport() try vm!.configuration.validateSaveRestoreSupport()
print("pausing VM to take a snapshot...") print("pausing VM to take a snapshot...")
try await vm!.virtualMachine.pause() try await vm!.virtualMachine.pause()
print("creating a snapshot...") print("creating a snapshot...")
try await vm!.virtualMachine.saveMachineStateTo(url: vmDir.stateURL) try await vm!.virtualMachine.saveMachineStateTo(url: vmDir.stateURL)
print("snapshot created successfully! shutting down the VM...") print("snapshot created successfully! shutting down the VM...")
task.cancel() task.cancel()
} else { } else {
print(RuntimeError.SuspendFailed("this functionality is only supported on macOS 14 (Sonoma) or newer")) print(RuntimeError.SuspendFailed("this functionality is only supported on macOS 14 (Sonoma) or newer"))
Foundation.exit(1) Foundation.exit(1)
} }
#endif #endif
} catch (let e) { } catch (let e) {
print(RuntimeError.SuspendFailed(e.localizedDescription)) print(RuntimeError.SuspendFailed(e.localizedDescription))
+108 -108
View File
@@ -8,129 +8,129 @@ struct UnsupportedHostOSError: Error, CustomStringConvertible {
#if arch(arm64) #if arch(arm64)
struct Darwin: PlatformSuspendable { struct Darwin: PlatformSuspendable {
var ecid: VZMacMachineIdentifier var ecid: VZMacMachineIdentifier
var hardwareModel: VZMacHardwareModel var hardwareModel: VZMacHardwareModel
init(ecid: VZMacMachineIdentifier, hardwareModel: VZMacHardwareModel) { init(ecid: VZMacMachineIdentifier, hardwareModel: VZMacHardwareModel) {
self.ecid = ecid self.ecid = ecid
self.hardwareModel = hardwareModel self.hardwareModel = hardwareModel
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let encodedECID = try container.decode(String.self, forKey: .ecid)
guard let data = Data.init(base64Encoded: encodedECID) else {
throw DecodingError.dataCorruptedError(forKey: .ecid,
in: container,
debugDescription: "failed to initialize Data using the provided value")
}
guard let ecid = VZMacMachineIdentifier.init(dataRepresentation: data) else {
throw DecodingError.dataCorruptedError(forKey: .ecid,
in: container,
debugDescription: "failed to initialize VZMacMachineIdentifier using the provided value")
}
self.ecid = ecid
let encodedHardwareModel = try container.decode(String.self, forKey: .hardwareModel)
guard let data = Data.init(base64Encoded: encodedHardwareModel) else {
throw DecodingError.dataCorruptedError(forKey: .hardwareModel, in: container, debugDescription: "")
}
guard let hardwareModel = VZMacHardwareModel.init(dataRepresentation: data) else {
throw DecodingError.dataCorruptedError(forKey: .hardwareModel, in: container, debugDescription: "")
}
self.hardwareModel = hardwareModel
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(ecid.dataRepresentation.base64EncodedString(), forKey: .ecid)
try container.encode(hardwareModel.dataRepresentation.base64EncodedString(), forKey: .hardwareModel)
}
func os() -> OS {
.darwin
}
func bootLoader(nvramURL: URL) throws -> VZBootLoader {
VZMacOSBootLoader()
}
func platform(nvramURL: URL) throws -> VZPlatformConfiguration {
let result = VZMacPlatformConfiguration()
result.machineIdentifier = ecid
result.auxiliaryStorage = VZMacAuxiliaryStorage(url: nvramURL)
if !hardwareModel.isSupported {
// At the moment support of M1 chip is not yet dropped in any macOS version
// This mean that host software is not supporting this hardware model and should be updated
throw UnsupportedHostOSError()
} }
result.hardwareModel = hardwareModel init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
return result let encodedECID = try container.decode(String.self, forKey: .ecid)
} guard let data = Data.init(base64Encoded: encodedECID) else {
throw DecodingError.dataCorruptedError(forKey: .ecid,
in: container,
debugDescription: "failed to initialize Data using the provided value")
}
guard let ecid = VZMacMachineIdentifier.init(dataRepresentation: data) else {
throw DecodingError.dataCorruptedError(forKey: .ecid,
in: container,
debugDescription: "failed to initialize VZMacMachineIdentifier using the provided value")
}
self.ecid = ecid
func graphicsDevice(vmConfig: VMConfig) -> VZGraphicsDeviceConfiguration { let encodedHardwareModel = try container.decode(String.self, forKey: .hardwareModel)
let result = VZMacGraphicsDeviceConfiguration() guard let data = Data.init(base64Encoded: encodedHardwareModel) else {
throw DecodingError.dataCorruptedError(forKey: .hardwareModel, in: container, debugDescription: "")
}
guard let hardwareModel = VZMacHardwareModel.init(dataRepresentation: data) else {
throw DecodingError.dataCorruptedError(forKey: .hardwareModel, in: container, debugDescription: "")
}
self.hardwareModel = hardwareModel
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(ecid.dataRepresentation.base64EncodedString(), forKey: .ecid)
try container.encode(hardwareModel.dataRepresentation.base64EncodedString(), forKey: .hardwareModel)
}
func os() -> OS {
.darwin
}
func bootLoader(nvramURL: URL) throws -> VZBootLoader {
VZMacOSBootLoader()
}
func platform(nvramURL: URL) throws -> VZPlatformConfiguration {
let result = VZMacPlatformConfiguration()
result.machineIdentifier = ecid
result.auxiliaryStorage = VZMacAuxiliaryStorage(url: nvramURL)
if !hardwareModel.isSupported {
// At the moment support of M1 chip is not yet dropped in any macOS version
// This mean that host software is not supporting this hardware model and should be updated
throw UnsupportedHostOSError()
}
result.hardwareModel = hardwareModel
return result
}
func graphicsDevice(vmConfig: VMConfig) -> VZGraphicsDeviceConfiguration {
let result = VZMacGraphicsDeviceConfiguration()
if let hostMainScreen = NSScreen.main {
let vmScreenSize = NSSize(width: vmConfig.display.width, height: vmConfig.display.height)
result.displays = [
VZMacGraphicsDisplayConfiguration(for: hostMainScreen, sizeInPoints: vmScreenSize)
]
return result
}
if let hostMainScreen = NSScreen.main {
let vmScreenSize = NSSize(width: vmConfig.display.width, height: vmConfig.display.height)
result.displays = [ result.displays = [
VZMacGraphicsDisplayConfiguration(for: hostMainScreen, sizeInPoints: vmScreenSize) VZMacGraphicsDisplayConfiguration(
widthInPixels: vmConfig.display.width,
heightInPixels: vmConfig.display.height,
// A reasonable guess according to Apple's documentation[1]
// [1]: https://developer.apple.com/documentation/coregraphics/1456599-cgdisplayscreensize
pixelsPerInch: 72
)
] ]
return result return result
} }
result.displays = [ func keyboards() -> [VZKeyboardConfiguration] {
VZMacGraphicsDisplayConfiguration( if #available(macOS 14, *) {
widthInPixels: vmConfig.display.width, // Mac keyboard is only supported by guests starting with macOS Ventura
heightInPixels: vmConfig.display.height, return [VZMacKeyboardConfiguration(), VZUSBKeyboardConfiguration()]
// A reasonable guess according to Apple's documentation[1] } else {
// [1]: https://developer.apple.com/documentation/coregraphics/1456599-cgdisplayscreensize return [VZUSBKeyboardConfiguration()]
pixelsPerInch: 72 }
) }
]
return result func keyboardsSuspendable() -> [VZKeyboardConfiguration] {
} if #available(macOS 14, *) {
return [VZMacKeyboardConfiguration()]
} else {
// fallback to the regular configuration
return keyboards()
}
}
func keyboards() -> [VZKeyboardConfiguration] { func pointingDevices() -> [VZPointingDeviceConfiguration] {
if #available(macOS 14, *) { // Trackpad is only supported by guests starting with macOS Ventura
// Mac keyboard is only supported by guests starting with macOS Ventura [VZMacTrackpadConfiguration(), VZUSBScreenCoordinatePointingDeviceConfiguration()]
return [VZMacKeyboardConfiguration(), VZUSBKeyboardConfiguration()] }
} else {
return [VZUSBKeyboardConfiguration()] func pointingDevicesSuspendable() -> [VZPointingDeviceConfiguration] {
if #available(macOS 14, *) {
return [VZMacTrackpadConfiguration()]
} else {
// fallback to the regular configuration
return pointingDevices()
}
} }
} }
func keyboardsSuspendable() -> [VZKeyboardConfiguration] {
if #available(macOS 14, *) {
return [VZMacKeyboardConfiguration()]
} else {
// fallback to the regular configuration
return keyboards()
}
}
func pointingDevices() -> [VZPointingDeviceConfiguration] {
// Trackpad is only supported by guests starting with macOS Ventura
[VZMacTrackpadConfiguration(), VZUSBScreenCoordinatePointingDeviceConfiguration()]
}
func pointingDevicesSuspendable() -> [VZPointingDeviceConfiguration] {
if #available(macOS 14, *) {
return [VZMacTrackpadConfiguration()]
} else {
// fallback to the regular configuration
return pointingDevices()
}
}
}
#endif #endif
+72 -72
View File
@@ -126,82 +126,82 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
} }
#if arch(arm64) #if arch(arm64)
init( init(
vmDir: VMDirectory, vmDir: VMDirectory,
ipswURL: URL, ipswURL: URL,
diskSizeGB: UInt16, diskSizeGB: UInt16,
network: Network = NetworkShared(), network: Network = NetworkShared(),
additionalStorageDevices: [VZStorageDeviceConfiguration] = [], additionalStorageDevices: [VZStorageDeviceConfiguration] = [],
directorySharingDevices: [VZDirectorySharingDeviceConfiguration] = [], directorySharingDevices: [VZDirectorySharingDeviceConfiguration] = [],
serialPorts: [VZSerialPortConfiguration] = [] serialPorts: [VZSerialPortConfiguration] = []
) async throws { ) async throws {
var ipswURL = ipswURL var ipswURL = ipswURL
if !ipswURL.isFileURL { if !ipswURL.isFileURL {
ipswURL = try await VM.retrieveIPSW(remoteURL: ipswURL) ipswURL = try await VM.retrieveIPSW(remoteURL: ipswURL)
}
// We create a temporary TART_HOME directory in tests, which has its "cache" folder symlinked
// to the users Tart cache directory (~/.tart/cache). However, the Virtualization.Framework
// cannot deal with paths that contain symlinks, so expand them here first.
ipswURL.resolveSymlinksInPath()
// Load the restore image and try to get the requirements
// that match both the image and our platform
let image = try await withCheckedThrowingContinuation { continuation in
VZMacOSRestoreImage.load(from: ipswURL) { result in
continuation.resume(with: result)
} }
}
guard let requirements = image.mostFeaturefulSupportedConfiguration else { // We create a temporary TART_HOME directory in tests, which has its "cache" folder symlinked
throw UnsupportedRestoreImageError() // to the users Tart cache directory (~/.tart/cache). However, the Virtualization.Framework
} // cannot deal with paths that contain symlinks, so expand them here first.
ipswURL.resolveSymlinksInPath()
// Create NVRAM // Load the restore image and try to get the requirements
_ = try VZMacAuxiliaryStorage(creatingStorageAt: vmDir.nvramURL, hardwareModel: requirements.hardwareModel) // that match both the image and our platform
let image = try await withCheckedThrowingContinuation { continuation in
// Create disk VZMacOSRestoreImage.load(from: ipswURL) { result in
try vmDir.resizeDisk(diskSizeGB)
name = vmDir.name
// Create config
config = VMConfig(
platform: Darwin(ecid: VZMacMachineIdentifier(), hardwareModel: requirements.hardwareModel),
cpuCountMin: requirements.minimumSupportedCPUCount,
memorySizeMin: requirements.minimumSupportedMemorySize
)
// allocate at least 4 CPUs because otherwise VMs are frequently freezing
try config.setCPU(cpuCount: max(4, requirements.minimumSupportedCPUCount))
try config.save(toURL: vmDir.configURL)
// Initialize the virtual machine and its configuration
self.network = network
configuration = try Self.craftConfiguration(diskURL: vmDir.diskURL, nvramURL: vmDir.nvramURL,
vmConfig: config, network: network,
additionalStorageDevices: additionalStorageDevices,
directorySharingDevices: directorySharingDevices,
serialPorts: serialPorts
)
virtualMachine = VZVirtualMachine(configuration: configuration)
super.init()
virtualMachine.delegate = self
// Run automated installation
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
DispatchQueue.main.async { [ipswURL] in
let installer = VZMacOSInstaller(virtualMachine: self.virtualMachine, restoringFromImageAt: ipswURL)
defaultLogger.appendNewLine("Installing OS...")
ProgressObserver(installer.progress).log(defaultLogger)
installer.install { result in
continuation.resume(with: result) continuation.resume(with: result)
} }
} }
guard let requirements = image.mostFeaturefulSupportedConfiguration else {
throw UnsupportedRestoreImageError()
}
// Create NVRAM
_ = try VZMacAuxiliaryStorage(creatingStorageAt: vmDir.nvramURL, hardwareModel: requirements.hardwareModel)
// Create disk
try vmDir.resizeDisk(diskSizeGB)
name = vmDir.name
// Create config
config = VMConfig(
platform: Darwin(ecid: VZMacMachineIdentifier(), hardwareModel: requirements.hardwareModel),
cpuCountMin: requirements.minimumSupportedCPUCount,
memorySizeMin: requirements.minimumSupportedMemorySize
)
// allocate at least 4 CPUs because otherwise VMs are frequently freezing
try config.setCPU(cpuCount: max(4, requirements.minimumSupportedCPUCount))
try config.save(toURL: vmDir.configURL)
// Initialize the virtual machine and its configuration
self.network = network
configuration = try Self.craftConfiguration(diskURL: vmDir.diskURL, nvramURL: vmDir.nvramURL,
vmConfig: config, network: network,
additionalStorageDevices: additionalStorageDevices,
directorySharingDevices: directorySharingDevices,
serialPorts: serialPorts
)
virtualMachine = VZVirtualMachine(configuration: configuration)
super.init()
virtualMachine.delegate = self
// Run automated installation
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
DispatchQueue.main.async { [ipswURL] in
let installer = VZMacOSInstaller(virtualMachine: self.virtualMachine, restoringFromImageAt: ipswURL)
defaultLogger.appendNewLine("Installing OS...")
ProgressObserver(installer.progress).log(defaultLogger)
installer.install { result in
continuation.resume(with: result)
}
}
}
} }
}
#endif #endif
@available(macOS 13, *) @available(macOS 13, *)
@@ -248,11 +248,11 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
@MainActor @MainActor
private func start(_ recovery: Bool) async throws { private func start(_ recovery: Bool) async throws {
#if arch(arm64) #if arch(arm64)
let startOptions = VZMacOSVirtualMachineStartOptions() let startOptions = VZMacOSVirtualMachineStartOptions()
startOptions.startUpFromMacOSRecovery = recovery startOptions.startUpFromMacOSRecovery = recovery
try await virtualMachine.start(options: startOptions) try await virtualMachine.start(options: startOptions)
#else #else
try await virtualMachine.start() try await virtualMachine.start()
#endif #endif
} }
+5 -5
View File
@@ -96,12 +96,12 @@ struct VMConfig: Codable {
switch os { switch os {
case .darwin: case .darwin:
#if arch(arm64) #if arch(arm64)
platform = try Darwin(from: decoder) platform = try Darwin(from: decoder)
#else #else
throw DecodingError.dataCorruptedError( throw DecodingError.dataCorruptedError(
forKey: .os, forKey: .os,
in: container, in: container,
debugDescription: "Darwin VMs are only supported on Apple Silicon hosts") debugDescription: "Darwin VMs are only supported on Apple Silicon hosts")
#endif #endif
case .linux: case .linux:
platform = try Linux(from: decoder) platform = try Linux(from: decoder)