mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
natlab: fix unixgram plumbing and add mac virtualization
Tweaked the unixgram plumbing to use the vm's remote unix address for write operations. Rudimentary macOS virtualization added which will spin up a VM with some hardcoded config options that work with natlabd's default settings in -dgram mode. Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
This commit is contained in:
parent
e6336fad18
commit
79ef5b32fe
4
.gitignore
vendored
4
.gitignore
vendored
@ -43,3 +43,7 @@ client/web/build/assets
|
||||
|
||||
/gocross
|
||||
/dist
|
||||
|
||||
# Ignore xcode userstate and workspace data
|
||||
*.xcuserstate
|
||||
*.xcworkspacedata
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
var (
|
||||
listen = flag.String("listen", "/tmp/qemu.sock", "path to listen on")
|
||||
write = flag.String("write", "/tmp/qemu_client.sock", "path to respond to (for dgram mode)")
|
||||
natType = flag.String("nat", "easy", "type of NAT to use")
|
||||
portmap = flag.Bool("portmap", false, "enable portmapping")
|
||||
dgram = flag.Bool("dgram", false, "enable datagram mode; for use with macOS Hypervisor.Framework and VZFileHandleNetworkDeviceAttachment")
|
||||
@ -65,15 +66,20 @@ func main() {
|
||||
var srv net.Listener
|
||||
var err error
|
||||
var conn *net.UnixConn
|
||||
var raddr *net.UnixAddr
|
||||
if *dgram {
|
||||
addr, err := net.ResolveUnixAddr("unixgram", *listen)
|
||||
laddr, err := net.ResolveUnixAddr("unixgram", *listen)
|
||||
if err != nil {
|
||||
log.Fatalf("ResolveUnixAddr: %v", err)
|
||||
}
|
||||
conn, err = net.ListenUnixgram("unixgram", addr)
|
||||
conn, err = net.ListenUnixgram("unixgram", laddr)
|
||||
if err != nil {
|
||||
log.Fatalf("ListenUnixgram: %v", err)
|
||||
}
|
||||
raddr, err = net.ResolveUnixAddr("unixgram", *write)
|
||||
if err != nil {
|
||||
log.Fatalf("ResolveUnixAddr: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
} else {
|
||||
srv, err = net.Listen("unix", *listen)
|
||||
@ -129,18 +135,21 @@ func main() {
|
||||
log.Fatalf("checkWorld: %v", err)
|
||||
}
|
||||
|
||||
if conn != nil {
|
||||
s.serveConn(conn)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
c, err := srv.Accept()
|
||||
if err != nil {
|
||||
log.Printf("Accept: %v", err)
|
||||
continue
|
||||
if *dgram {
|
||||
if conn != nil && raddr != nil {
|
||||
s.serveConn(conn, raddr)
|
||||
} else {
|
||||
log.Fatalf("no conn or raddr in dgram mode. no packets for you")
|
||||
}
|
||||
} else {
|
||||
for {
|
||||
c, err := srv.Accept()
|
||||
if err != nil {
|
||||
log.Printf("Accept: %v", err)
|
||||
continue
|
||||
}
|
||||
go s.serveConn(c.(*net.UnixConn), nil)
|
||||
}
|
||||
go s.serveConn(c.(*net.UnixConn))
|
||||
}
|
||||
}
|
||||
|
||||
@ -572,31 +581,42 @@ func (s *Server) IPv4ForDNS(qname string) (netip.Addr, bool) {
|
||||
}
|
||||
|
||||
// serveConn serves a single connection from a client.
|
||||
func (s *Server) serveConn(uc *net.UnixConn) {
|
||||
// raddr is the remote address, if known for dgram clients
|
||||
func (s *Server) serveConn(uc *net.UnixConn, raddr *net.UnixAddr) {
|
||||
log.Printf("Got conn %T %p", uc, uc)
|
||||
defer uc.Close()
|
||||
|
||||
bw := bufio.NewWriterSize(uc, 2<<10)
|
||||
var writeMu sync.Mutex
|
||||
writePkt := func(pkt []byte) {
|
||||
if pkt == nil {
|
||||
return
|
||||
var writePkt func([]byte)
|
||||
|
||||
if *dgram {
|
||||
writePkt = func(pkt []byte) {
|
||||
if _, err := uc.WriteToUnix(pkt, raddr); err != nil {
|
||||
log.Printf("Write pkt failed: %v", err)
|
||||
return
|
||||
}
|
||||
log.Printf("Write pkt: %v", pkt)
|
||||
}
|
||||
writeMu.Lock()
|
||||
defer writeMu.Unlock()
|
||||
if !*dgram { // i.e. qemu mode
|
||||
} else {
|
||||
bw := bufio.NewWriterSize(uc, 2<<10)
|
||||
var writeMu sync.Mutex
|
||||
writePkt = func(pkt []byte) {
|
||||
if pkt == nil {
|
||||
return
|
||||
}
|
||||
writeMu.Lock()
|
||||
defer writeMu.Unlock()
|
||||
hdr := binary.BigEndian.AppendUint32(bw.AvailableBuffer()[:0], uint32(len(pkt)))
|
||||
if _, err := bw.Write(hdr); err != nil {
|
||||
log.Printf("Write hdr: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if _, err := bw.Write(pkt); err != nil {
|
||||
log.Printf("Write pkt: %v", err)
|
||||
return
|
||||
}
|
||||
if err := bw.Flush(); err != nil {
|
||||
log.Printf("Flush: %v", err)
|
||||
if _, err := bw.Write(pkt); err != nil {
|
||||
log.Printf("Write pkt: %v", err)
|
||||
return
|
||||
}
|
||||
if err := bw.Flush(); err != nil {
|
||||
log.Printf("Flush: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1
natlab/vnetMacHost/Configuration/SampleCode.xcconfig
Normal file
1
natlab/vnetMacHost/Configuration/SampleCode.xcconfig
Normal file
@ -0,0 +1 @@
|
||||
|
8
natlab/vnetMacHost/InstallationTool.entitlements
Normal file
8
natlab/vnetMacHost/InstallationTool.entitlements
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.virtualization</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
8
natlab/vnetMacHost/LICENSE/LICENSE.txt
Normal file
8
natlab/vnetMacHost/LICENSE/LICENSE.txt
Normal file
@ -0,0 +1,8 @@
|
||||
Copyright © 2023 Apple Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
20
natlab/vnetMacHost/Swift/Common/Config.swift
Normal file
20
natlab/vnetMacHost/Swift/Common/Config.swift
Normal file
@ -0,0 +1,20 @@
|
||||
import Foundation
|
||||
|
||||
// We need to make this all configurable via config file of some kind and
|
||||
// read it in.
|
||||
struct Config {
|
||||
static let mac = "5a:94:ef:e4:0c:ee"
|
||||
static let serverSocket = "/tmp/qemu.sock"
|
||||
static let clientSocket = "/tmp/qemu_client.sock"
|
||||
|
||||
static let memorySize = (4 * 1024 * 1024 * 1024) as UInt64
|
||||
}
|
||||
|
||||
let vmBundlePath = NSHomeDirectory() + "/VM.bundle/"
|
||||
let vmBundleURL = URL(fileURLWithPath: vmBundlePath)
|
||||
let auxiliaryStorageURL = vmBundleURL.appendingPathComponent("AuxiliaryStorage")
|
||||
let diskImageURL = vmBundleURL.appendingPathComponent("Disk.img")
|
||||
let hardwareModelURL = vmBundleURL.appendingPathComponent("HardwareModel")
|
||||
let machineIdentifierURL = vmBundleURL.appendingPathComponent("MachineIdentifier")
|
||||
let restoreImageURL = vmBundleURL.appendingPathComponent("RestoreImage.ipsw")
|
||||
let saveFileURL = vmBundleURL.appendingPathComponent("SaveFile.vzvmsave")
|
21
natlab/vnetMacHost/Swift/Common/VnetDelegate.swift
Normal file
21
natlab/vnetMacHost/Swift/Common/VnetDelegate.swift
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
See the LICENSE.txt file for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
A class that conforms to `VZVirtualMachineDelegate` and tracks the virtual machine's state.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Virtualization
|
||||
|
||||
class VnetDelegate: NSObject, VZVirtualMachineDelegate {
|
||||
func virtualMachine(_ virtualMachine: VZVirtualMachine, didStopWithError error: Error) {
|
||||
NSLog("Virtual machine did stop with error: \(error.localizedDescription)")
|
||||
exit(-1)
|
||||
}
|
||||
|
||||
func guestDidStop(_ virtualMachine: VZVirtualMachine) {
|
||||
NSLog("Guest did stop virtual machine.")
|
||||
exit(0)
|
||||
}
|
||||
}
|
126
natlab/vnetMacHost/Swift/Common/VnetHostConfigHelper.swift
Normal file
126
natlab/vnetMacHost/Swift/Common/VnetHostConfigHelper.swift
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
See the LICENSE.txt file for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
The helper that creates various configuration objects exposed in the `VZVirtualMachineConfiguration`.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Virtualization
|
||||
|
||||
#if arch(arm64)
|
||||
|
||||
struct VnetHostConfigHelper {
|
||||
static func computeCPUCount() -> Int {
|
||||
let totalAvailableCPUs = ProcessInfo.processInfo.processorCount
|
||||
|
||||
var virtualCPUCount = totalAvailableCPUs <= 1 ? 1 : totalAvailableCPUs - 1
|
||||
virtualCPUCount = max(virtualCPUCount, VZVirtualMachineConfiguration.minimumAllowedCPUCount)
|
||||
virtualCPUCount = min(virtualCPUCount, VZVirtualMachineConfiguration.maximumAllowedCPUCount)
|
||||
|
||||
return virtualCPUCount
|
||||
}
|
||||
|
||||
static func computeMemorySize() -> UInt64 {
|
||||
// Set the amount of system memory to 4 GB; this is a baseline value
|
||||
// that you can change depending on your use case.
|
||||
var memorySize = Config.memorySize
|
||||
memorySize = max(memorySize, VZVirtualMachineConfiguration.minimumAllowedMemorySize)
|
||||
memorySize = min(memorySize, VZVirtualMachineConfiguration.maximumAllowedMemorySize)
|
||||
|
||||
return memorySize
|
||||
}
|
||||
|
||||
static func createBootLoader() -> VZMacOSBootLoader {
|
||||
return VZMacOSBootLoader()
|
||||
}
|
||||
|
||||
static func createGraphicsDeviceConfiguration() -> VZMacGraphicsDeviceConfiguration {
|
||||
let graphicsConfiguration = VZMacGraphicsDeviceConfiguration()
|
||||
graphicsConfiguration.displays = [
|
||||
// The system arbitrarily chooses the resolution of the display to be 1920 x 1200.
|
||||
VZMacGraphicsDisplayConfiguration(widthInPixels: 1920, heightInPixels: 1200, pixelsPerInch: 80)
|
||||
]
|
||||
|
||||
return graphicsConfiguration
|
||||
}
|
||||
|
||||
static func createBlockDeviceConfiguration() -> VZVirtioBlockDeviceConfiguration {
|
||||
guard let diskImageAttachment = try? VZDiskImageStorageDeviceAttachment(url: diskImageURL, readOnly: false) else {
|
||||
fatalError("Failed to create Disk image.")
|
||||
}
|
||||
let disk = VZVirtioBlockDeviceConfiguration(attachment: diskImageAttachment)
|
||||
return disk
|
||||
}
|
||||
|
||||
static func createNetworkDeviceConfiguration() -> VZVirtioNetworkDeviceConfiguration {
|
||||
let networkDevice = VZVirtioNetworkDeviceConfiguration()
|
||||
networkDevice.macAddress = VZMACAddress(string: Config.mac)!
|
||||
|
||||
let socket = Darwin.socket(AF_UNIX, SOCK_DGRAM, 0)
|
||||
|
||||
let serverSocket = Config.serverSocket
|
||||
let clientSocket = Config.clientSocket
|
||||
|
||||
unlink(clientSocket)
|
||||
var clientAddr = sockaddr_un()
|
||||
clientAddr.sun_family = sa_family_t(AF_UNIX)
|
||||
clientSocket.withCString { ptr in
|
||||
withUnsafeMutablePointer(to: &clientAddr.sun_path.0) { dest in
|
||||
_ = strcpy(dest, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
let bindRes = Darwin.bind(socket,
|
||||
withUnsafePointer(to: &clientAddr, { $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { $0 } }),
|
||||
socklen_t(MemoryLayout<sockaddr_un>.size))
|
||||
|
||||
if bindRes == -1 {
|
||||
print("Error binding virtual network client socket - \(String(cString: strerror(errno)))")
|
||||
return networkDevice
|
||||
}
|
||||
|
||||
var serverAddr = sockaddr_un()
|
||||
serverAddr.sun_family = sa_family_t(AF_UNIX)
|
||||
serverSocket.withCString { ptr in
|
||||
withUnsafeMutablePointer(to: &serverAddr.sun_path.0) { dest in
|
||||
_ = strcpy(dest, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
let connectRes = Darwin.connect(socket,
|
||||
withUnsafePointer(to: &serverAddr, { $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { $0 } }),
|
||||
socklen_t(MemoryLayout<sockaddr_un>.size))
|
||||
|
||||
|
||||
if connectRes == -1 {
|
||||
print("Error binding virtual network server socket - \(String(cString: strerror(errno)))")
|
||||
return networkDevice
|
||||
}
|
||||
|
||||
print("Virtual if mac address is \(Config.mac)")
|
||||
print("Client bound to \(clientSocket)")
|
||||
print("Connected to server at \(serverSocket)")
|
||||
print("Socket fd is \(socket)")
|
||||
|
||||
|
||||
let handle = FileHandle(fileDescriptor: socket)
|
||||
let device = VZFileHandleNetworkDeviceAttachment(fileHandle: handle)
|
||||
networkDevice.attachment = device
|
||||
return networkDevice
|
||||
}
|
||||
|
||||
static func createPointingDeviceConfiguration() -> VZPointingDeviceConfiguration {
|
||||
return VZMacTrackpadConfiguration()
|
||||
}
|
||||
|
||||
static func createKeyboardConfiguration() -> VZKeyboardConfiguration {
|
||||
if #available(macOS 14.0, *) {
|
||||
return VZMacKeyboardConfiguration()
|
||||
} else {
|
||||
return VZUSBKeyboardConfiguration()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
See the LICENSE.txt file for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Download the latest macOS restore image from the network.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Virtualization
|
||||
|
||||
#if arch(arm64)
|
||||
|
||||
class MacOSRestoreImage: NSObject {
|
||||
private var downloadObserver: NSKeyValueObservation?
|
||||
|
||||
// MARK: Observe the download progress.
|
||||
|
||||
public func download(completionHandler: @escaping () -> Void) {
|
||||
NSLog("Attempting to download latest available restore image.")
|
||||
VZMacOSRestoreImage.fetchLatestSupported { [self](result: Result<VZMacOSRestoreImage, Error>) in
|
||||
switch result {
|
||||
case let .failure(error):
|
||||
fatalError(error.localizedDescription)
|
||||
|
||||
case let .success(restoreImage):
|
||||
downloadRestoreImage(restoreImage: restoreImage, completionHandler: completionHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Download the restore image from the network.
|
||||
|
||||
private func downloadRestoreImage(restoreImage: VZMacOSRestoreImage, completionHandler: @escaping () -> Void) {
|
||||
let downloadTask = URLSession.shared.downloadTask(with: restoreImage.url) { localURL, response, error in
|
||||
if let error = error {
|
||||
fatalError("Download failed. \(error.localizedDescription).")
|
||||
}
|
||||
|
||||
guard (try? FileManager.default.moveItem(at: localURL!, to: restoreImageURL)) != nil else {
|
||||
fatalError("Failed to move downloaded restore image to \(restoreImageURL).")
|
||||
}
|
||||
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
downloadObserver = downloadTask.progress.observe(\.fractionCompleted, options: [.initial, .new]) { (progress, change) in
|
||||
NSLog("Restore image download progress: \(change.newValue! * 100).")
|
||||
}
|
||||
downloadTask.resume()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,169 @@
|
||||
/*
|
||||
See the LICENSE.txt file for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
A helper class to install a macOS virtual machine.
|
||||
*/
|
||||
|
||||
import Virtualization
|
||||
|
||||
#if arch(arm64)
|
||||
|
||||
class MacOSVirtualMachineInstaller: NSObject {
|
||||
private var installationObserver: NSKeyValueObservation?
|
||||
private var virtualMachine: VZVirtualMachine!
|
||||
private var virtualMachineResponder: VnetDelegate?
|
||||
|
||||
// Create a bundle on the user's Home directory to store any artifacts
|
||||
// that the installation produces.
|
||||
public func setUpVirtualMachineArtifacts() {
|
||||
createVMBundle()
|
||||
}
|
||||
|
||||
// MARK: Install macOS onto the virtual machine from IPSW.
|
||||
|
||||
public func installMacOS(ipswURL: URL) {
|
||||
NSLog("Attempting to install from IPSW at \(ipswURL).")
|
||||
VZMacOSRestoreImage.load(from: ipswURL, completionHandler: { [self](result: Result<VZMacOSRestoreImage, Error>) in
|
||||
switch result {
|
||||
case let .failure(error):
|
||||
fatalError(error.localizedDescription)
|
||||
|
||||
case let .success(restoreImage):
|
||||
installMacOS(restoreImage: restoreImage)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: - Internal helper functions.
|
||||
|
||||
private func installMacOS(restoreImage: VZMacOSRestoreImage) {
|
||||
guard let macOSConfiguration = restoreImage.mostFeaturefulSupportedConfiguration else {
|
||||
fatalError("No supported configuration available.")
|
||||
}
|
||||
|
||||
if !macOSConfiguration.hardwareModel.isSupported {
|
||||
fatalError("macOSConfiguration configuration isn't supported on the current host.")
|
||||
}
|
||||
|
||||
DispatchQueue.main.async { [self] in
|
||||
setupVirtualMachine(macOSConfiguration: macOSConfiguration)
|
||||
startInstallation(restoreImageURL: restoreImage.url)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Create the Mac platform configuration.
|
||||
|
||||
private func createMacPlatformConfiguration(macOSConfiguration: VZMacOSConfigurationRequirements) -> VZMacPlatformConfiguration {
|
||||
let macPlatformConfiguration = VZMacPlatformConfiguration()
|
||||
|
||||
guard let auxiliaryStorage = try? VZMacAuxiliaryStorage(creatingStorageAt: auxiliaryStorageURL,
|
||||
hardwareModel: macOSConfiguration.hardwareModel,
|
||||
options: []) else {
|
||||
fatalError("Failed to create auxiliary storage.")
|
||||
}
|
||||
macPlatformConfiguration.auxiliaryStorage = auxiliaryStorage
|
||||
macPlatformConfiguration.hardwareModel = macOSConfiguration.hardwareModel
|
||||
macPlatformConfiguration.machineIdentifier = VZMacMachineIdentifier()
|
||||
|
||||
// Store the hardware model and machine identifier to disk so that you
|
||||
// can retrieve them for subsequent boots.
|
||||
try! macPlatformConfiguration.hardwareModel.dataRepresentation.write(to: hardwareModelURL)
|
||||
try! macPlatformConfiguration.machineIdentifier.dataRepresentation.write(to: machineIdentifierURL)
|
||||
|
||||
return macPlatformConfiguration
|
||||
}
|
||||
|
||||
// MARK: Create the virtual machine configuration and instantiate the virtual machine.
|
||||
|
||||
private func setupVirtualMachine(macOSConfiguration: VZMacOSConfigurationRequirements) {
|
||||
let virtualMachineConfiguration = VZVirtualMachineConfiguration()
|
||||
|
||||
virtualMachineConfiguration.platform = createMacPlatformConfiguration(macOSConfiguration: macOSConfiguration)
|
||||
virtualMachineConfiguration.cpuCount = VnetHostConfigHelper.computeCPUCount()
|
||||
if virtualMachineConfiguration.cpuCount < macOSConfiguration.minimumSupportedCPUCount {
|
||||
fatalError("CPUCount isn't supported by the macOS configuration.")
|
||||
}
|
||||
|
||||
virtualMachineConfiguration.memorySize = VnetHostConfigHelper.computeMemorySize()
|
||||
if virtualMachineConfiguration.memorySize < macOSConfiguration.minimumSupportedMemorySize {
|
||||
fatalError("memorySize isn't supported by the macOS configuration.")
|
||||
}
|
||||
|
||||
// Create a 128 GB disk image.
|
||||
createDiskImage()
|
||||
|
||||
virtualMachineConfiguration.bootLoader = VnetHostConfigHelper.createBootLoader()
|
||||
virtualMachineConfiguration.graphicsDevices = [VnetHostConfigHelper.createGraphicsDeviceConfiguration()]
|
||||
virtualMachineConfiguration.storageDevices = [VnetHostConfigHelper.createBlockDeviceConfiguration()]
|
||||
virtualMachineConfiguration.networkDevices = [VnetHostConfigHelper.createNetworkDeviceConfiguration()]
|
||||
virtualMachineConfiguration.pointingDevices = [VnetHostConfigHelper.createPointingDeviceConfiguration()]
|
||||
virtualMachineConfiguration.keyboards = [VnetHostConfigHelper.createKeyboardConfiguration()]
|
||||
|
||||
try! virtualMachineConfiguration.validate()
|
||||
|
||||
if #available(macOS 14.0, *) {
|
||||
try! virtualMachineConfiguration.validateSaveRestoreSupport()
|
||||
}
|
||||
|
||||
virtualMachine = VZVirtualMachine(configuration: virtualMachineConfiguration)
|
||||
virtualMachineResponder = VnetDelegate()
|
||||
virtualMachine.delegate = virtualMachineResponder
|
||||
}
|
||||
|
||||
// MARK: Begin macOS installation.
|
||||
|
||||
private func startInstallation(restoreImageURL: URL) {
|
||||
let installer = VZMacOSInstaller(virtualMachine: virtualMachine, restoringFromImageAt: restoreImageURL)
|
||||
|
||||
NSLog("Starting installation.")
|
||||
installer.install(completionHandler: { (result: Result<Void, Error>) in
|
||||
if case let .failure(error) = result {
|
||||
fatalError(error.localizedDescription)
|
||||
} else {
|
||||
NSLog("Installation succeeded.")
|
||||
}
|
||||
})
|
||||
|
||||
// Observe installation progress.
|
||||
installationObserver = installer.progress.observe(\.fractionCompleted, options: [.initial, .new]) { (progress, change) in
|
||||
NSLog("Installation progress: \(change.newValue! * 100).")
|
||||
}
|
||||
}
|
||||
|
||||
private func createVMBundle() {
|
||||
let bundleFd = mkdir(vmBundlePath, S_IRWXU | S_IRWXG | S_IRWXO)
|
||||
if bundleFd == -1 {
|
||||
if errno == EEXIST {
|
||||
fatalError("Failed to create VM.bundle: the base directory already exists.")
|
||||
}
|
||||
fatalError("Failed to create VM.bundle.")
|
||||
}
|
||||
|
||||
let result = close(bundleFd)
|
||||
if result != 0 {
|
||||
fatalError("Failed to close VM.bundle.")
|
||||
}
|
||||
}
|
||||
|
||||
// Create an empty disk image for the virtual machine.
|
||||
private func createDiskImage() {
|
||||
let diskFd = open(diskImageURL.path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)
|
||||
if diskFd == -1 {
|
||||
fatalError("Cannot create disk image.")
|
||||
}
|
||||
|
||||
// 128 GB disk space.
|
||||
var result = ftruncate(diskFd, 128 * 1024 * 1024 * 1024)
|
||||
if result != 0 {
|
||||
fatalError("ftruncate() failed.")
|
||||
}
|
||||
|
||||
result = close(diskFd)
|
||||
if result != 0 {
|
||||
fatalError("Failed to close the disk image.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
44
natlab/vnetMacHost/Swift/InstallationTool/main.swift
Normal file
44
natlab/vnetMacHost/Swift/InstallationTool/main.swift
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
See the LICENSE.txt file for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
The entry for `InstallationTool`.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
#if arch(arm64)
|
||||
|
||||
let installer = MacOSVirtualMachineInstaller()
|
||||
|
||||
if CommandLine.arguments.count == 2 {
|
||||
let ipswPath = String(CommandLine.arguments[1])
|
||||
let ipswURL = URL(fileURLWithPath: ipswPath)
|
||||
guard ipswURL.isFileURL else {
|
||||
fatalError("The provided IPSW path is not a valid file URL.")
|
||||
}
|
||||
|
||||
installer.setUpVirtualMachineArtifacts()
|
||||
installer.installMacOS(ipswURL: ipswURL)
|
||||
|
||||
dispatchMain()
|
||||
} else if CommandLine.arguments.count == 1 {
|
||||
installer.setUpVirtualMachineArtifacts()
|
||||
|
||||
let restoreImage = MacOSRestoreImage()
|
||||
restoreImage.download {
|
||||
// Install from the restore image that you downloaded.
|
||||
installer.installMacOS(ipswURL: restoreImageURL)
|
||||
}
|
||||
|
||||
dispatchMain()
|
||||
} else {
|
||||
NSLog("Invalid argument. Please either provide the path to an IPSW file, or run this tool without any argument.")
|
||||
exit(-1)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
NSLog("This tool can only be run on Apple Silicon Macs.")
|
||||
|
||||
#endif
|
196
natlab/vnetMacHost/Swift/vnetMacHost/AppDelegate.swift
Normal file
196
natlab/vnetMacHost/Swift/vnetMacHost/AppDelegate.swift
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
See the LICENSE.txt file for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
The app delegate that sets up and starts the virtual machine.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
import Foundation
|
||||
import Virtualization
|
||||
|
||||
@main
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
@IBOutlet var window: NSWindow!
|
||||
|
||||
@IBOutlet weak var virtualMachineView: VZVirtualMachineView!
|
||||
|
||||
private var virtualMachineResponder: VnetDelegate?
|
||||
|
||||
private var virtualMachine: VZVirtualMachine!
|
||||
|
||||
// MARK: Create the Mac platform configuration.
|
||||
|
||||
#if arch(arm64)
|
||||
private func createMacPlaform() -> VZMacPlatformConfiguration {
|
||||
let macPlatform = VZMacPlatformConfiguration()
|
||||
|
||||
let auxiliaryStorage = VZMacAuxiliaryStorage(contentsOf: auxiliaryStorageURL)
|
||||
macPlatform.auxiliaryStorage = auxiliaryStorage
|
||||
|
||||
if !FileManager.default.fileExists(atPath: vmBundlePath) {
|
||||
fatalError("Missing Virtual Machine Bundle at \(vmBundlePath). Run InstallationTool first to create it.")
|
||||
}
|
||||
|
||||
// Retrieve the hardware model and save this value to disk
|
||||
// during installation.
|
||||
guard let hardwareModelData = try? Data(contentsOf: hardwareModelURL) else {
|
||||
fatalError("Failed to retrieve hardware model data.")
|
||||
}
|
||||
|
||||
guard let hardwareModel = VZMacHardwareModel(dataRepresentation: hardwareModelData) else {
|
||||
fatalError("Failed to create hardware model.")
|
||||
}
|
||||
|
||||
if !hardwareModel.isSupported {
|
||||
fatalError("The hardware model isn't supported on the current host")
|
||||
}
|
||||
macPlatform.hardwareModel = hardwareModel
|
||||
|
||||
// Retrieve the machine identifier and save this value to disk
|
||||
// during installation.
|
||||
guard let machineIdentifierData = try? Data(contentsOf: machineIdentifierURL) else {
|
||||
fatalError("Failed to retrieve machine identifier data.")
|
||||
}
|
||||
|
||||
guard let machineIdentifier = VZMacMachineIdentifier(dataRepresentation: machineIdentifierData) else {
|
||||
fatalError("Failed to create machine identifier.")
|
||||
}
|
||||
macPlatform.machineIdentifier = machineIdentifier
|
||||
|
||||
return macPlatform
|
||||
}
|
||||
|
||||
// MARK: Create the virtual machine configuration and instantiate the virtual machine.
|
||||
|
||||
private func createVirtualMachine() {
|
||||
let virtualMachineConfiguration = VZVirtualMachineConfiguration()
|
||||
|
||||
virtualMachineConfiguration.platform = createMacPlaform()
|
||||
virtualMachineConfiguration.bootLoader = VnetHostConfigHelper.createBootLoader()
|
||||
virtualMachineConfiguration.cpuCount = VnetHostConfigHelper.computeCPUCount()
|
||||
virtualMachineConfiguration.memorySize = VnetHostConfigHelper.computeMemorySize()
|
||||
virtualMachineConfiguration.graphicsDevices = [VnetHostConfigHelper.createGraphicsDeviceConfiguration()]
|
||||
virtualMachineConfiguration.storageDevices = [VnetHostConfigHelper.createBlockDeviceConfiguration()]
|
||||
virtualMachineConfiguration.networkDevices = [VnetHostConfigHelper.createNetworkDeviceConfiguration()]
|
||||
virtualMachineConfiguration.pointingDevices = [VnetHostConfigHelper.createPointingDeviceConfiguration()]
|
||||
virtualMachineConfiguration.keyboards = [VnetHostConfigHelper.createKeyboardConfiguration()]
|
||||
|
||||
try! virtualMachineConfiguration.validate()
|
||||
|
||||
if #available(macOS 14.0, *) {
|
||||
try! virtualMachineConfiguration.validateSaveRestoreSupport()
|
||||
}
|
||||
|
||||
virtualMachine = VZVirtualMachine(configuration: virtualMachineConfiguration)
|
||||
}
|
||||
|
||||
// MARK: Start or restore the virtual machine.
|
||||
|
||||
func startVirtualMachine() {
|
||||
virtualMachine.start(completionHandler: { (result) in
|
||||
if case let .failure(error) = result {
|
||||
fatalError("Virtual machine failed to start with \(error)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func resumeVirtualMachine() {
|
||||
virtualMachine.resume(completionHandler: { (result) in
|
||||
if case let .failure(error) = result {
|
||||
fatalError("Virtual machine failed to resume with \(error)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@available(macOS 14.0, *)
|
||||
func restoreVirtualMachine() {
|
||||
virtualMachine.restoreMachineStateFrom(url: saveFileURL, completionHandler: { [self] (error) in
|
||||
// Remove the saved file. Whether success or failure, the state no longer matches the VM's disk.
|
||||
let fileManager = FileManager.default
|
||||
try! fileManager.removeItem(at: saveFileURL)
|
||||
|
||||
if error == nil {
|
||||
self.resumeVirtualMachine()
|
||||
} else {
|
||||
self.startVirtualMachine()
|
||||
}
|
||||
})
|
||||
}
|
||||
#endif
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
#if arch(arm64)
|
||||
DispatchQueue.main.async { [self] in
|
||||
createVirtualMachine()
|
||||
virtualMachineResponder = VnetDelegate()
|
||||
virtualMachine.delegate = virtualMachineResponder
|
||||
virtualMachineView.virtualMachine = virtualMachine
|
||||
virtualMachineView.capturesSystemKeys = true
|
||||
|
||||
if #available(macOS 14.0, *) {
|
||||
// Configure the app to automatically respond to changes in the display size.
|
||||
virtualMachineView.automaticallyReconfiguresDisplay = true
|
||||
}
|
||||
|
||||
if #available(macOS 14.0, *) {
|
||||
let fileManager = FileManager.default
|
||||
if fileManager.fileExists(atPath: saveFileURL.path) {
|
||||
restoreVirtualMachine()
|
||||
} else {
|
||||
startVirtualMachine()
|
||||
}
|
||||
} else {
|
||||
startVirtualMachine()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: Save the virtual machine when the app exits.
|
||||
|
||||
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
#if arch(arm64)
|
||||
@available(macOS 14.0, *)
|
||||
func saveVirtualMachine(completionHandler: @escaping () -> Void) {
|
||||
virtualMachine.saveMachineStateTo(url: saveFileURL, completionHandler: { (error) in
|
||||
guard error == nil else {
|
||||
fatalError("Virtual machine failed to save with \(error!)")
|
||||
}
|
||||
|
||||
completionHandler()
|
||||
})
|
||||
}
|
||||
|
||||
@available(macOS 14.0, *)
|
||||
func pauseAndSaveVirtualMachine(completionHandler: @escaping () -> Void) {
|
||||
virtualMachine.pause(completionHandler: { (result) in
|
||||
if case let .failure(error) = result {
|
||||
fatalError("Virtual machine failed to pause with \(error)")
|
||||
}
|
||||
|
||||
self.saveVirtualMachine(completionHandler: completionHandler)
|
||||
})
|
||||
}
|
||||
#endif
|
||||
|
||||
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
|
||||
#if arch(arm64)
|
||||
if #available(macOS 14.0, *) {
|
||||
if virtualMachine.state == .running {
|
||||
pauseAndSaveVirtualMachine(completionHandler: {
|
||||
sender.reply(toApplicationShouldTerminate: true)
|
||||
})
|
||||
|
||||
return .terminateLater
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return .terminateNow
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
696
natlab/vnetMacHost/Swift/vnetMacHost/Base.lproj/MainMenu.xib
Normal file
696
natlab/vnetMacHost/Swift/vnetMacHost/Base.lproj/MainMenu.xib
Normal file
@ -0,0 +1,696 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22690"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="macOSVirtualMachineSampleApp_Swift" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="virtualMachineView" destination="EiT-Mj-1SZ" id="KBI-Ak-yeW"/>
|
||||
<outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="vnetMacHost" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="vnetMacHost" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About vnetMacHost" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide vnetMacHost" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Save and quit vnetMacHost" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="dMs-cI-mzQ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H">
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
|
||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
|
||||
<connections>
|
||||
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
||||
<menuItem title="Find" id="4EN-yA-p0u">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Format" id="jxT-CU-nIS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
|
||||
<items>
|
||||
<menuItem title="Font" id="Gi5-1S-RQB">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
|
||||
<items>
|
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
|
||||
<connections>
|
||||
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
|
||||
<connections>
|
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
|
||||
<connections>
|
||||
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
|
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
|
||||
<connections>
|
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
|
||||
<menuItem title="Kern" id="jBQ-r6-VK2">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="GUa-eO-cwY">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="cDB-IK-hbR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Tighten" id="46P-cB-AYj">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Loosen" id="ogc-rX-tC1">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Ligatures" id="o6e-r0-MWq">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="agt-UL-0e3">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use None" id="J7y-lM-qPV">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use All" id="xQD-1f-W4t">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Baseline" id="OaQ-X3-Vso">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
|
||||
<items>
|
||||
<menuItem title="Use Default" id="3Om-Ey-2VK">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Superscript" id="Rqc-34-cIF">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Subscript" id="I0S-gh-46l">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Raise" id="2h7-ER-AoG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Lower" id="1tx-W0-xDw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
|
||||
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
|
||||
<connections>
|
||||
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
|
||||
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Text" id="Fal-I4-PZk">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Text" id="d9c-me-L2H">
|
||||
<items>
|
||||
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
|
||||
<connections>
|
||||
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
|
||||
<connections>
|
||||
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Justify" id="J5U-5w-g23">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
|
||||
<connections>
|
||||
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
|
||||
<menuItem title="Writing Direction" id="H1b-Si-o9J">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
|
||||
<items>
|
||||
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="YGs-j5-SAR">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="Lbh-J2-qVU">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="jFq-tB-4Kx">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
|
||||
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem id="Nop-cj-93Q">
|
||||
<string key="title"> Default</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="BgM-ve-c93">
|
||||
<string key="title"> Left to Right</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem id="RB4-Sm-HuC">
|
||||
<string key="title"> Right to Left</string>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
|
||||
<menuItem title="Show Ruler" id="vLm-3I-IUL">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
|
||||
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleSidebar:" target="-1" id="iwa-gc-5KM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="wpr-3q-Mcd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||
<items>
|
||||
<menuItem title="vnetMacHost Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
<point key="canvasLocation" x="200" y="121"/>
|
||||
</menu>
|
||||
<window title="vnetMacHost" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="960" height="600"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
|
||||
<view key="contentView" id="EiT-Mj-1SZ" customClass="VZVirtualMachineView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="960" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</view>
|
||||
<point key="canvasLocation" x="200" y="400"/>
|
||||
</window>
|
||||
</objects>
|
||||
</document>
|
5
natlab/vnetMacHost/Swift/vnetMacHost/Info.plist
Normal file
5
natlab/vnetMacHost/Swift/vnetMacHost/Info.plist
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
</plist>
|
8
natlab/vnetMacHost/vnetMacHost.entitlements
Normal file
8
natlab/vnetMacHost/vnetMacHost.entitlements
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.virtualization</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<array/>
|
||||
</plist>
|
544
natlab/vnetMacHost/vnetMacHost.xcodeproj/project.pbxproj
Normal file
544
natlab/vnetMacHost/vnetMacHost.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,544 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 55;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
8F87D52126C34111000EADA4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F87D52026C34111000EADA4 /* AppDelegate.swift */; };
|
||||
8F87D52326C34111000EADA4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8F87D52226C34111000EADA4 /* Assets.xcassets */; };
|
||||
8F87D52626C34111000EADA4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8F87D52426C34111000EADA4 /* MainMenu.xib */; };
|
||||
8F87D53426C341AC000EADA4 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F87D53326C341AC000EADA4 /* main.swift */; };
|
||||
8F87D53A26C3423F000EADA4 /* MacOSVirtualMachineInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F87D53926C3423F000EADA4 /* MacOSVirtualMachineInstaller.swift */; };
|
||||
8F87D54026C34259000EADA4 /* VnetHostConfigHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F87D53D26C34259000EADA4 /* VnetHostConfigHelper.swift */; };
|
||||
8F87D54126C34259000EADA4 /* VnetDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F87D53E26C34259000EADA4 /* VnetDelegate.swift */; };
|
||||
8F87D54326C34265000EADA4 /* VnetDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F87D53E26C34259000EADA4 /* VnetDelegate.swift */; };
|
||||
8F87D54426C34269000EADA4 /* VnetHostConfigHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F87D53D26C34259000EADA4 /* VnetHostConfigHelper.swift */; };
|
||||
8F87D54726C3427C000EADA4 /* Virtualization.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F87D54626C3427C000EADA4 /* Virtualization.framework */; };
|
||||
8F87D54826C34286000EADA4 /* Virtualization.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F87D54626C3427C000EADA4 /* Virtualization.framework */; };
|
||||
8FB90BEE26D5AC8100988F51 /* MacOSRestoreImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FB90BED26D5AC8100988F51 /* MacOSRestoreImage.swift */; };
|
||||
C266EA7F2C5D2AD800DC57E3 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = C266EA7E2C5D2AD800DC57E3 /* Config.swift */; };
|
||||
C266EA802C5D2AE700DC57E3 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = C266EA7E2C5D2AD800DC57E3 /* Config.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
8F87D52F26C341AC000EADA4 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
8F87D51D26C34111000EADA4 /* vnetMacHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vnetMacHost.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8F87D52026C34111000EADA4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
8F87D52226C34111000EADA4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
8F87D52526C34111000EADA4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
8F87D53126C341AC000EADA4 /* InstallationTool-Swift */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "InstallationTool-Swift"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8F87D53326C341AC000EADA4 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
8F87D53826C3423F000EADA4 /* InstallationTool.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = InstallationTool.entitlements; sourceTree = "<group>"; };
|
||||
8F87D53926C3423F000EADA4 /* MacOSVirtualMachineInstaller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacOSVirtualMachineInstaller.swift; sourceTree = "<group>"; };
|
||||
8F87D53B26C34250000EADA4 /* vnetMacHost.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = vnetMacHost.entitlements; sourceTree = "<group>"; };
|
||||
8F87D53D26C34259000EADA4 /* VnetHostConfigHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VnetHostConfigHelper.swift; sourceTree = "<group>"; };
|
||||
8F87D53E26C34259000EADA4 /* VnetDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VnetDelegate.swift; sourceTree = "<group>"; };
|
||||
8F87D54626C3427C000EADA4 /* Virtualization.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Virtualization.framework; path = System/Library/Frameworks/Virtualization.framework; sourceTree = SDKROOT; };
|
||||
8FB90BE826D422FD00988F51 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
8FB90BED26D5AC8100988F51 /* MacOSRestoreImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacOSRestoreImage.swift; sourceTree = "<group>"; };
|
||||
B0E246092DFBF28FAEA2709F /* LICENSE.txt */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE.txt; sourceTree = "<group>"; };
|
||||
C266EA7E2C5D2AD800DC57E3 /* Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = "<group>"; };
|
||||
F4E72614B21833A4E0FE3E98 /* SampleCode.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = SampleCode.xcconfig; path = Configuration/SampleCode.xcconfig; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
8F87D51A26C34111000EADA4 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8F87D54826C34286000EADA4 /* Virtualization.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8F87D52E26C341AC000EADA4 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8F87D54726C3427C000EADA4 /* Virtualization.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
09E329497FB7E44895839D88 /* LICENSE */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B0E246092DFBF28FAEA2709F /* LICENSE.txt */,
|
||||
);
|
||||
path = LICENSE;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3026A0D16D3A077128FE4194 /* Configuration */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4E72614B21833A4E0FE3E98 /* SampleCode.xcconfig */,
|
||||
);
|
||||
name = Configuration;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F87D51426C34111000EADA4 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F87D53B26C34250000EADA4 /* vnetMacHost.entitlements */,
|
||||
8F87D53826C3423F000EADA4 /* InstallationTool.entitlements */,
|
||||
8FDABC17270D0F9100D7FC60 /* Swift */,
|
||||
8F87D51E26C34111000EADA4 /* Products */,
|
||||
8F87D54526C3427C000EADA4 /* Frameworks */,
|
||||
3026A0D16D3A077128FE4194 /* Configuration */,
|
||||
09E329497FB7E44895839D88 /* LICENSE */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F87D51E26C34111000EADA4 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F87D51D26C34111000EADA4 /* vnetMacHost.app */,
|
||||
8F87D53126C341AC000EADA4 /* InstallationTool-Swift */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F87D51F26C34111000EADA4 /* vnetMacHost */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F87D52026C34111000EADA4 /* AppDelegate.swift */,
|
||||
8F87D52226C34111000EADA4 /* Assets.xcassets */,
|
||||
8F87D52426C34111000EADA4 /* MainMenu.xib */,
|
||||
8FB90BE826D422FD00988F51 /* Info.plist */,
|
||||
);
|
||||
path = vnetMacHost;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F87D52C26C3418F000EADA4 /* Common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C266EA7E2C5D2AD800DC57E3 /* Config.swift */,
|
||||
8F87D53D26C34259000EADA4 /* VnetHostConfigHelper.swift */,
|
||||
8F87D53E26C34259000EADA4 /* VnetDelegate.swift */,
|
||||
);
|
||||
path = Common;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F87D53226C341AC000EADA4 /* InstallationTool */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8FB90BED26D5AC8100988F51 /* MacOSRestoreImage.swift */,
|
||||
8F87D53926C3423F000EADA4 /* MacOSVirtualMachineInstaller.swift */,
|
||||
8F87D53326C341AC000EADA4 /* main.swift */,
|
||||
);
|
||||
path = InstallationTool;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8F87D54526C3427C000EADA4 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F87D54626C3427C000EADA4 /* Virtualization.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8FDABC17270D0F9100D7FC60 /* Swift */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F87D52C26C3418F000EADA4 /* Common */,
|
||||
8F87D51F26C34111000EADA4 /* vnetMacHost */,
|
||||
8F87D53226C341AC000EADA4 /* InstallationTool */,
|
||||
);
|
||||
path = Swift;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
8F87D51C26C34111000EADA4 /* vnetMacHost-Swift */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8F87D52926C34111000EADA4 /* Build configuration list for PBXNativeTarget "vnetMacHost-Swift" */;
|
||||
buildPhases = (
|
||||
8F87D51926C34111000EADA4 /* Sources */,
|
||||
8F87D51A26C34111000EADA4 /* Frameworks */,
|
||||
8F87D51B26C34111000EADA4 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "vnetMacHost-Swift";
|
||||
productName = macOSVirtualMachineSampleApp;
|
||||
productReference = 8F87D51D26C34111000EADA4 /* vnetMacHost.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
8F87D53026C341AC000EADA4 /* InstallationTool-Swift */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8F87D53526C341AC000EADA4 /* Build configuration list for PBXNativeTarget "InstallationTool-Swift" */;
|
||||
buildPhases = (
|
||||
8F87D52D26C341AC000EADA4 /* Sources */,
|
||||
8F87D52E26C341AC000EADA4 /* Frameworks */,
|
||||
8F87D52F26C341AC000EADA4 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "InstallationTool-Swift";
|
||||
productName = InstallationTool;
|
||||
productReference = 8F87D53126C341AC000EADA4 /* InstallationTool-Swift */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
8F87D51526C34111000EADA4 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
DefaultBuildSystemTypeForWorkspace = Latest;
|
||||
LastSwiftUpdateCheck = 1300;
|
||||
LastUpgradeCheck = 1300;
|
||||
ORGANIZATIONNAME = Apple;
|
||||
TargetAttributes = {
|
||||
8F87D51C26C34111000EADA4 = {
|
||||
CreatedOnToolsVersion = 13.0;
|
||||
};
|
||||
8F87D53026C341AC000EADA4 = {
|
||||
CreatedOnToolsVersion = 13.0;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 8F87D51826C34111000EADA4 /* Build configuration list for PBXProject "vnetMacHost" */;
|
||||
compatibilityVersion = "Xcode 13.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 8F87D51426C34111000EADA4;
|
||||
productRefGroup = 8F87D51E26C34111000EADA4 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
8F87D51C26C34111000EADA4 /* vnetMacHost-Swift */,
|
||||
8F87D53026C341AC000EADA4 /* InstallationTool-Swift */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
8F87D51B26C34111000EADA4 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8F87D52326C34111000EADA4 /* Assets.xcassets in Resources */,
|
||||
8F87D52626C34111000EADA4 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
8F87D51926C34111000EADA4 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8F87D52126C34111000EADA4 /* AppDelegate.swift in Sources */,
|
||||
8F87D54126C34259000EADA4 /* VnetDelegate.swift in Sources */,
|
||||
C266EA7F2C5D2AD800DC57E3 /* Config.swift in Sources */,
|
||||
8F87D54026C34259000EADA4 /* VnetHostConfigHelper.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8F87D52D26C341AC000EADA4 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8F87D54426C34269000EADA4 /* VnetHostConfigHelper.swift in Sources */,
|
||||
C266EA802C5D2AE700DC57E3 /* Config.swift in Sources */,
|
||||
8F87D53A26C3423F000EADA4 /* MacOSVirtualMachineInstaller.swift in Sources */,
|
||||
8FB90BEE26D5AC8100988F51 /* MacOSRestoreImage.swift in Sources */,
|
||||
8F87D54326C34265000EADA4 /* VnetDelegate.swift in Sources */,
|
||||
8F87D53426C341AC000EADA4 /* main.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
8F87D52426C34111000EADA4 /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
8F87D52526C34111000EADA4 /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
8F87D52726C34111000EADA4 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F4E72614B21833A4E0FE3E98 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8F87D52826C34111000EADA4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F4E72614B21833A4E0FE3E98 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8F87D52A26C34111000EADA4 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F4E72614B21833A4E0FE3E98 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = vnetMacHost.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = W5364U7YZB;
|
||||
ENABLE_APP_SANDBOX = NO;
|
||||
ENABLE_USER_SELECTED_FILES = readwrite;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = Swift/vnetMacHost/Info.plist;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSMainNibFile = MainMenu;
|
||||
INFOPLIST_KEY_NSMicrophoneUsageDescription = "Allow for using audio input devices.";
|
||||
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tailscale.vnetMacHost;
|
||||
PRODUCT_NAME = vnetMacHost;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8F87D52B26C34111000EADA4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F4E72614B21833A4E0FE3E98 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = vnetMacHost.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = W5364U7YZB;
|
||||
ENABLE_APP_SANDBOX = NO;
|
||||
ENABLE_USER_SELECTED_FILES = readwrite;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = Swift/vnetMacHost/Info.plist;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSMainNibFile = MainMenu;
|
||||
INFOPLIST_KEY_NSMicrophoneUsageDescription = "Allow for using audio input devices.";
|
||||
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tailscale.vnetMacHost;
|
||||
PRODUCT_NAME = vnetMacHost;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8F87D53626C341AC000EADA4 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F4E72614B21833A4E0FE3E98 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = InstallationTool.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = W5364U7YZB;
|
||||
ENABLE_USER_SELECTED_FILES = readwrite;
|
||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tailscale.vnetMacHostSetupTool;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8F87D53726C341AC000EADA4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F4E72614B21833A4E0FE3E98 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = InstallationTool.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = W5364U7YZB;
|
||||
ENABLE_USER_SELECTED_FILES = readwrite;
|
||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tailscale.vnetMacHostSetupTool;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
8F87D51826C34111000EADA4 /* Build configuration list for PBXProject "vnetMacHost" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8F87D52726C34111000EADA4 /* Debug */,
|
||||
8F87D52826C34111000EADA4 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8F87D52926C34111000EADA4 /* Build configuration list for PBXNativeTarget "vnetMacHost-Swift" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8F87D52A26C34111000EADA4 /* Debug */,
|
||||
8F87D52B26C34111000EADA4 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8F87D53526C341AC000EADA4 /* Build configuration list for PBXNativeTarget "InstallationTool-Swift" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8F87D53626C341AC000EADA4 /* Debug */,
|
||||
8F87D53726C341AC000EADA4 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 8F87D51526C34111000EADA4 /* Project object */;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildSystemType</key>
|
||||
<string>Latest</string>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1320"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8F87D53026C341AC000EADA4"
|
||||
BuildableName = "InstallationTool-Swift"
|
||||
BlueprintName = "InstallationTool-Swift"
|
||||
ReferencedContainer = "container:vnetMacHost.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8F87D53026C341AC000EADA4"
|
||||
BuildableName = "InstallationTool-Swift"
|
||||
BlueprintName = "InstallationTool-Swift"
|
||||
ReferencedContainer = "container:vnetMacHost.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8F87D53026C341AC000EADA4"
|
||||
BuildableName = "InstallationTool-Swift"
|
||||
BlueprintName = "InstallationTool-Swift"
|
||||
ReferencedContainer = "container:vnetMacHost.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1320"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8F87D51C26C34111000EADA4"
|
||||
BuildableName = "vnetMacHost.app"
|
||||
BlueprintName = "vnetMacHost-Swift"
|
||||
ReferencedContainer = "container:vnetMacHost.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8F87D51C26C34111000EADA4"
|
||||
BuildableName = "vnetMacHost.app"
|
||||
BlueprintName = "vnetMacHost-Swift"
|
||||
ReferencedContainer = "container:vnetMacHost.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8F87D51C26C34111000EADA4"
|
||||
BuildableName = "vnetMacHost.app"
|
||||
BlueprintName = "vnetMacHost-Swift"
|
||||
ReferencedContainer = "container:vnetMacHost.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>8FDABC39270D1DC600D7FC60</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>8FDABC58270D1FFE00D7FC60</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
Loading…
Reference in New Issue
Block a user