Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2022 Business & EducationSystem Services

WWDC22 · 23 min · Business & Education / System Services

Create macOS or Linux virtual machines

Learn how you can use the Virtualization framework to quickly create virtual machines on your Mac. We’ll show you how to create a virtual Mac and quickly test changes to your app in an isolated environment. We’ll also explore how you can install and run full Linux distributions on Apple silicon, and share how you can take advantage of Rosetta 2 to run x86-64 Linux binaries.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 16 snippets

Running the virtual machine swift · at 4:11 ↗
let virtualMachine = VZVirtualMachine(configuration: configuration)
try await virtualMachine.start()
Showing the virtual machine’s display swift · at 4:33 ↗
let virtualMachineView = VZVirtualMachineView()
virtualMachineView.virtualMachine = virtualMachine
Start from the base swift · at 7:43 ↗
var configuration = VZVirtualMachineConfiguration()
configuration.cpuCount = 4
configuration.memorySize = (4 * 1024 * 1024 * 1024) as UInt64
configuration.storageDevices = [newBlockDevice()]
configuration.pointingDevices = [newPointingDevice()]
Set up the platform swift · at 7:47 ↗
let platform = VZMacPlatformConfiguration()

let hardwareModel = VZMacHardwareModel(dataRepresentation: savedHardwareModel)
platform.hardwareModel = hardwareModel!

let auxiliaryStorage = VZMacAuxiliaryStorage(contentsOf: auxiliaryStorageURL)
platform.auxiliaryStorage = auxiliaryStorage

let machineIdentifier = VZMacMachineIdentifier(dataRepresentation: savedIdentifier)
platform.machineIdentifier = machineIdentifier!

configuration.platform = platform
Boot loader swift · at 8:31 ↗
configuration.bootLoader = VZMacOSBootLoader()
1. Getting an image swift · at 9:16 ↗
let restoreImage = try await VZMacOSRestoreImage.latestSupported

try await download(restoreImage.url)
2. Create a compatible configuration swift · at 9:29 ↗
let requirements = restoreImage.mostFeaturefulSupportedConfiguration

guard let requirements = requirements else {
    // No compatible configuration.
    return
}

platform.hardwareModel = requirements.hardwareModel

configuration.cpuCount = requirements.minimumSupportedCPUCount
configuration.memorySize = requirements.minimumSupportedMemorySize
3. Install macOS swift · at 10:10 ↗
let virtualMachine = VZVirtualMachine(configuration: configuration)

let installer = VZMacOSInstaller(virtualMachine: virtualMachine,
                                 restoringFromImageAt: imageURL)
try await installer.install()
Setting up GPU acceleration swift · at 10:58 ↗
let graphicsConfiguration = VZMacGraphicsDeviceConfiguration()
graphicsConfiguration.displays = [
    VZMacGraphicsDisplayConfiguration(widthInPixels: 1920,
                                      heightInPixels: 1200,
                                      pixelsPerInch: 80)
]

configuration.graphicsDevices = [graphicsConfiguration]
Setting up the Mac trackpad swift · at 11:48 ↗
let trackpad = VZMacTrackpadConfiguration()
configuration.pointingDevices = [trackpad]
Share a folder swift · at 12:33 ↗
let sharedDirectory = VZSharedDirectory(url: directoryURL, readOnly: false)
let share = VZSingleDirectoryShare(directory: sharedDirectory)

let tag = VZVirtioFileSystemDeviceConfiguration.macOSGuestAutomountTag
let sharingDevice = VZVirtioFileSystemDeviceConfiguration(tag: tag)
sharingDevice.share = share

configuration.directorySharingDevices = [sharingDevice]
Setting up USB Mass Storage device configuration swift · at 16:10 ↗
let diskImageURL = URL(fileURLWithPath: "linux.iso")
let attachment = try! VZDiskImageStorageDeviceAttachment(url: diskImageURL, readOnly: true)
let usbDeviceConfiguration = VZUSBMassStorageDeviceConfiguration(attachment: attachment)

configuration.storageDevices = [usbDeviceConfiguration, createBlockDevice()]
Booting Linux swift · at 17:27 ↗
let efi = VZEFIBootLoader()
efi.variableStore = VZEFIVariableStore(creatingVariableStoreAt: storeURL,
                                       options: [])
configuration.bootLoader = efi
Setting up Virtio graphics swift · at 18:24 ↗
let virtioGPU = VZVirtioGraphicsDeviceConfiguration()
virtioGPU.scanouts = [
    VZVirtioGraphicsScanoutConfiguration(widthInPixels: 1280, heightInPixels: 720)
]

configuration.graphicsDevices = [virtioGPU]
Setting up Rosetta swift · at 21:02 ↗
let rosettaDirectoryShare = try! VZLinuxRosettaDirectoryShare()
let directorySharingDevice = VZVirtioFileSystemDeviceConfiguration(tag: "RosettaShare")
directorySharingDevice.share = rosettaDirectoryShare

configuration.directorySharingDevices = [directorySharingDevice]
Setting up Linux bash · at 21:37 ↗
mount -t virtiofs RosettaShare /mnt/Rosetta

sudo /usr/sbin/update-binfmts --install rosetta /mnt/Rosetta/rosetta \
  --magic "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00" \
  --mask "\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" \
  --credentials yes --preserve no --fix-binary yes

Resources