initial commit
This commit is contained in:
commit
bccff31856
11 changed files with 876 additions and 0 deletions
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# See LICENSE folder for this sample’s licensing information.
|
||||
#
|
||||
# Apple sample code gitignore configuration.
|
||||
|
||||
# Finder
|
||||
.DS_Store
|
||||
|
||||
# Xcode - User files
|
||||
xcuserdata/
|
||||
|
||||
**/*.xcodeproj/project.xcworkspace/*
|
||||
!**/*.xcodeproj/project.xcworkspace/xcshareddata
|
||||
|
||||
**/*.xcodeproj/project.xcworkspace/xcshareddata/*
|
||||
!**/*.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
|
||||
|
||||
**/*.playground/playground.xcworkspace/*
|
||||
!**/*.playground/playground.xcworkspace/xcshareddata
|
||||
|
||||
**/*.playground/playground.xcworkspace/xcshareddata/*
|
||||
!**/*.playground/playground.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
|
13
Configuration/SampleCode.xcconfig
Normal file
13
Configuration/SampleCode.xcconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// See LICENSE folder for this sample’s licensing information.
|
||||
//
|
||||
// SampleCode.xcconfig
|
||||
//
|
||||
|
||||
// The `SAMPLE_CODE_DISAMBIGUATOR` configuration is to make it easier to build
|
||||
// and run a sample code project. Once you set your project's development team,
|
||||
// you'll have a unique bundle identifier. This is because the bundle identifier
|
||||
// is derived based on the 'SAMPLE_CODE_DISAMBIGUATOR' value. Do not use this
|
||||
// approach in your own projects—it's only useful for sample code projects because
|
||||
// they are frequently downloaded and don't have a development team set.
|
||||
SAMPLE_CODE_DISAMBIGUATOR=${DEVELOPMENT_TEAM}
|
8
LICENSE/LICENSE.txt
Normal file
8
LICENSE/LICENSE.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Copyright © 2021 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.
|
||||
|
5
LinuxVirtualMachine.xcodeproj/.xcodesamplecode.plist
Normal file
5
LinuxVirtualMachine.xcodeproj/.xcodesamplecode.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">
|
||||
<array/>
|
||||
</plist>
|
329
LinuxVirtualMachine.xcodeproj/project.pbxproj
Normal file
329
LinuxVirtualMachine.xcodeproj/project.pbxproj
Normal file
|
@ -0,0 +1,329 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
374FD25B24CBADD100890848 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374FD25A24CBADD100890848 /* main.swift */; };
|
||||
4852D4A62A19B60500D8F0C2 /* FileDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4852D4A52A19B60500D8F0C2 /* FileDownloader.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
374FD25524CBADD100890848 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
374FD25724CBADD100890848 /* LinuxVirtualMachine */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = LinuxVirtualMachine; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
374FD25A24CBADD100890848 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
374FD26124CBAE6700890848 /* LinuxVirtualMachine.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LinuxVirtualMachine.entitlements; sourceTree = "<group>"; };
|
||||
3B6662F3321F8749BDBDDB08 /* LICENSE.txt */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE.txt; sourceTree = "<group>"; };
|
||||
415EB883448D759F3C023B32 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
4852D4A52A19B60500D8F0C2 /* FileDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDownloader.swift; sourceTree = "<group>"; };
|
||||
E3865CF719CB3E4197A4D3A9 /* SampleCode.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = SampleCode.xcconfig; path = Configuration/SampleCode.xcconfig; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
374FD25424CBADD100890848 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
374FD24E24CBADD100890848 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
415EB883448D759F3C023B32 /* README.md */,
|
||||
374FD25924CBADD100890848 /* LinuxVirtualMachine */,
|
||||
374FD25824CBADD100890848 /* Products */,
|
||||
7311A096A816DCB7003B6B98 /* Configuration */,
|
||||
84CE507934101D4167798E3C /* LICENSE */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
374FD25824CBADD100890848 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
374FD25724CBADD100890848 /* LinuxVirtualMachine */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
374FD25924CBADD100890848 /* LinuxVirtualMachine */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
374FD25A24CBADD100890848 /* main.swift */,
|
||||
374FD26124CBAE6700890848 /* LinuxVirtualMachine.entitlements */,
|
||||
4852D4A52A19B60500D8F0C2 /* FileDownloader.swift */,
|
||||
);
|
||||
path = LinuxVirtualMachine;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7311A096A816DCB7003B6B98 /* Configuration */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E3865CF719CB3E4197A4D3A9 /* SampleCode.xcconfig */,
|
||||
);
|
||||
name = Configuration;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84CE507934101D4167798E3C /* LICENSE */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B6662F3321F8749BDBDDB08 /* LICENSE.txt */,
|
||||
);
|
||||
path = LICENSE;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
374FD25624CBADD100890848 /* LinuxVirtualMachine */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 374FD25E24CBADD100890848 /* Build configuration list for PBXNativeTarget "LinuxVirtualMachine" */;
|
||||
buildPhases = (
|
||||
374FD25324CBADD100890848 /* Sources */,
|
||||
374FD25424CBADD100890848 /* Frameworks */,
|
||||
374FD25524CBADD100890848 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = LinuxVirtualMachine;
|
||||
productName = LinuxVirtualMachine;
|
||||
productReference = 374FD25724CBADD100890848 /* LinuxVirtualMachine */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
374FD24F24CBADD100890848 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1200;
|
||||
LastUpgradeCheck = 1200;
|
||||
ORGANIZATIONNAME = Apple;
|
||||
TargetAttributes = {
|
||||
374FD25624CBADD100890848 = {
|
||||
CreatedOnToolsVersion = 12.0;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 374FD25224CBADD100890848 /* Build configuration list for PBXProject "LinuxVirtualMachine" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 374FD24E24CBADD100890848;
|
||||
productRefGroup = 374FD25824CBADD100890848 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
374FD25624CBADD100890848 /* LinuxVirtualMachine */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
374FD25324CBADD100890848 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4852D4A62A19B60500D8F0C2 /* FileDownloader.swift in Sources */,
|
||||
374FD25B24CBADD100890848 /* main.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
374FD25C24CBADD100890848 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E3865CF719CB3E4197A4D3A9 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
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 = 11.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;
|
||||
};
|
||||
374FD25D24CBADD100890848 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E3865CF719CB3E4197A4D3A9 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
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 = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
374FD25F24CBADD100890848 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E3865CF719CB3E4197A4D3A9 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = LinuxVirtualMachine/LinuxVirtualMachine.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = C8Z9PRF4VH;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.linuxvirtualmachine${SAMPLE_CODE_DISAMBIGUATOR}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
374FD26024CBADD100890848 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E3865CF719CB3E4197A4D3A9 /* SampleCode.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = LinuxVirtualMachine/LinuxVirtualMachine.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = C8Z9PRF4VH;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.linuxvirtualmachine${SAMPLE_CODE_DISAMBIGUATOR}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
374FD25224CBADD100890848 /* Build configuration list for PBXProject "LinuxVirtualMachine" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
374FD25C24CBADD100890848 /* Debug */,
|
||||
374FD25D24CBADD100890848 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
374FD25E24CBADD100890848 /* Build configuration list for PBXNativeTarget "LinuxVirtualMachine" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
374FD25F24CBADD100890848 /* Debug */,
|
||||
374FD26024CBADD100890848 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 374FD24F24CBADD100890848 /* 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>BuildSystemType</key>
|
||||
<string>Latest</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1200"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "374FD25624CBADD100890848"
|
||||
BuildableName = "LinuxVirtualMachine"
|
||||
BlueprintName = "LinuxVirtualMachine"
|
||||
ReferencedContainer = "container:LinuxVirtualMachine.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 = "374FD25624CBADD100890848"
|
||||
BuildableName = "LinuxVirtualMachine"
|
||||
BlueprintName = "LinuxVirtualMachine"
|
||||
ReferencedContainer = "container:LinuxVirtualMachine.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "374FD25624CBADD100890848"
|
||||
BuildableName = "LinuxVirtualMachine"
|
||||
BlueprintName = "LinuxVirtualMachine"
|
||||
ReferencedContainer = "container:LinuxVirtualMachine.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
94
LinuxVirtualMachine/FileDownloader.swift
Normal file
94
LinuxVirtualMachine/FileDownloader.swift
Normal file
|
@ -0,0 +1,94 @@
|
|||
import Foundation
|
||||
|
||||
class FileDownloader {
|
||||
|
||||
static func loadFileSync(url: URL, completion: @escaping (String?, Error?) -> Void)
|
||||
{
|
||||
if #available(macOS 13.0, *) {
|
||||
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let guixUrl = URL(filePath: NSHomeDirectory() + "/.guix/guix.bundle/guix.tar.gz")
|
||||
|
||||
let destinationUrl = guixUrl
|
||||
|
||||
if FileManager().fileExists(atPath: destinationUrl.path)
|
||||
{
|
||||
print("File already exists [\(destinationUrl.path)]")
|
||||
completion(destinationUrl.path, nil)
|
||||
}
|
||||
else if let dataFromURL = NSData(contentsOf: url)
|
||||
{
|
||||
if dataFromURL.write(to: destinationUrl, atomically: true)
|
||||
{
|
||||
print("file saved [\(destinationUrl.path)]")
|
||||
completion(destinationUrl.path, nil)
|
||||
}
|
||||
else
|
||||
{
|
||||
print("error saving file")
|
||||
let error = NSError(domain:"Error saving file", code:1001, userInfo:nil)
|
||||
completion(destinationUrl.path, error)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
let error = NSError(domain:"Error downloading file", code:1002, userInfo:nil)
|
||||
completion(destinationUrl.path, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func loadFileAsync(url: URL, completion: @escaping (String?, Error?) -> Void)
|
||||
{
|
||||
if #available(macOS 13.0, *) {
|
||||
|
||||
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
|
||||
let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent)
|
||||
|
||||
if FileManager().fileExists(atPath: destinationUrl.path)
|
||||
{
|
||||
print("File already exists [\(destinationUrl.path)]")
|
||||
completion(destinationUrl.path, nil)
|
||||
}
|
||||
else
|
||||
{
|
||||
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: nil)
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "GET"
|
||||
let task = session.dataTask(with: request, completionHandler:
|
||||
{
|
||||
data, response, error in
|
||||
if error == nil
|
||||
{
|
||||
if let response = response as? HTTPURLResponse
|
||||
{
|
||||
if response.statusCode == 200
|
||||
{
|
||||
if let data = data
|
||||
{
|
||||
if let _ = try? data.write(to: destinationUrl, options: Data.WritingOptions.atomic)
|
||||
{
|
||||
completion(destinationUrl.path, error)
|
||||
}
|
||||
else
|
||||
{
|
||||
completion(destinationUrl.path, error)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
completion(destinationUrl.path, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
completion(destinationUrl.path, error)
|
||||
}
|
||||
})
|
||||
task.resume()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
LinuxVirtualMachine/LinuxVirtualMachine.entitlements
Normal file
8
LinuxVirtualMachine/LinuxVirtualMachine.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>
|
281
LinuxVirtualMachine/main.swift
Normal file
281
LinuxVirtualMachine/main.swift
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
A command-line utility that runs Linux in a virtual machine.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Virtualization
|
||||
|
||||
class Delegate: NSObject {
|
||||
}
|
||||
|
||||
|
||||
class MySocketListenerDelegate: NSObject, VZVirtioSocketListenerDelegate {
|
||||
func listener(_ listener: VZVirtioSocketListener, shouldAcceptNewConnection connection: VZVirtioSocketConnection, from device: VZVirtioSocketDevice) -> Bool {
|
||||
// Implement your logic to decide whether to accept the new connection
|
||||
// For example, you may always accept:
|
||||
return true
|
||||
|
||||
// Or, you might want to check some properties of the connection or device and decide based on that
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension Delegate: VZVirtualMachineDelegate {
|
||||
func guestDidStop(_ virtualMachine: VZVirtualMachine) {
|
||||
print("The guest shut down. Exiting.")
|
||||
exit(EXIT_SUCCESS)
|
||||
}
|
||||
}
|
||||
if #available(macOS 13.0, *) {
|
||||
|
||||
let vmBundlePath = NSHomeDirectory() + "/.guix/guix.bundle/"
|
||||
let mainDiskImagePath = vmBundlePath + "guix-raw.img"
|
||||
let efiVariableStorePath = vmBundlePath + "NVRAM"
|
||||
let machineIdentifierPath = vmBundlePath + "MachineIdentifier"
|
||||
var needsInstall = true
|
||||
|
||||
// MARK: Parse the Command Line
|
||||
|
||||
|
||||
// MARK: Create the Virtual Machine Configuration
|
||||
print(shell("/bin/zsh ~/.guix/startup-script.sh"))
|
||||
|
||||
|
||||
if !FileManager.default.fileExists(atPath: vmBundlePath) {
|
||||
needsInstall = true
|
||||
// createVMBundle()
|
||||
print(shell("mkdir ~/.guix && mkdir ~/.guix/home"))
|
||||
|
||||
print(shell("cp -r /Applications/Guix.app/Contents/Resources/home/ssh-cert ~/.guix/"))
|
||||
|
||||
print(shell("cp /Applications/Guix.app/Contents/Resources/home/*.sh ~/.guix/"))
|
||||
do {
|
||||
try FileManager.default.createDirectory(atPath: vmBundlePath, withIntermediateDirectories: false)
|
||||
} catch {
|
||||
fatalError("Failed to create “GUI Linux VM.bundle.”")
|
||||
}
|
||||
print("The main system image is now downloading. This may take a few minutes...")
|
||||
// createMainDiskImage()
|
||||
let url = URL(string: "https://objectstorage.us-phoenix-1.oraclecloud.com/n/axfgkze2xif1/b/guix-system/o/msg-system-aarch64guix-raw.img.tar.gz")
|
||||
FileDownloader.loadFileSync(url: url!) { (path, error) in
|
||||
print("File downloaded to : \(path!)")
|
||||
}
|
||||
print(shell("tar -xvzf ~/.guix/guix.bundle/guix.tar.gz -C ~/.guix/guix.bundle/"))
|
||||
//print(shell("/opt/homebrew/bin/qemu-img convert ~/.guix/guix.bundle/guix-raw.qcow2 ~/.guix/guix.bundle/guix-raw.img"))
|
||||
|
||||
|
||||
// configureAndStartVirtualMachine()
|
||||
} else {
|
||||
needsInstall = false
|
||||
// configureAndStartVirtualMachine()
|
||||
}
|
||||
|
||||
let configuration = VZVirtualMachineConfiguration()
|
||||
let platform = VZGenericPlatformConfiguration()
|
||||
let bootloader = VZEFIBootLoader()
|
||||
let disksArray = NSMutableArray()
|
||||
|
||||
//set cpu count
|
||||
let totalAvailableCPUs = ProcessInfo.processInfo.processorCount
|
||||
|
||||
var virtualCPUCount = totalAvailableCPUs <= 1 ? 1 : totalAvailableCPUs - 1
|
||||
virtualCPUCount = max(virtualCPUCount, VZVirtualMachineConfiguration.minimumAllowedCPUCount)
|
||||
virtualCPUCount = min(virtualCPUCount, VZVirtualMachineConfiguration.maximumAllowedCPUCount)
|
||||
configuration.cpuCount = virtualCPUCount
|
||||
|
||||
//set memory size
|
||||
var memorySize = (4 * 1024 * 1024 * 1024) as UInt64 // 4 GiB
|
||||
memorySize = max(memorySize, VZVirtualMachineConfiguration.minimumAllowedMemorySize)
|
||||
memorySize = min(memorySize, VZVirtualMachineConfiguration.maximumAllowedMemorySize)
|
||||
configuration.memorySize = memorySize // 2 GiB
|
||||
|
||||
|
||||
if needsInstall {
|
||||
// This is a fresh install: Create a new machine identifier and EFI variable store,
|
||||
// and configure a USB mass storage device to boot the ISO image.
|
||||
|
||||
let machineIdentifier = VZGenericMachineIdentifier()
|
||||
|
||||
|
||||
// Store the machine identifier to disk so you can retrieve it for subsequent boots.
|
||||
try! machineIdentifier.dataRepresentation.write(to: URL(fileURLWithPath: machineIdentifierPath))
|
||||
|
||||
platform.machineIdentifier = machineIdentifier
|
||||
|
||||
guard let efiVariableStore = try? VZEFIVariableStore(creatingVariableStoreAt: URL(fileURLWithPath: efiVariableStorePath)) else {
|
||||
fatalError("Failed to create the EFI variable store.")
|
||||
}
|
||||
|
||||
bootloader.variableStore = efiVariableStore
|
||||
// disksArray.add(createUSBMassStorageDeviceConfiguration())
|
||||
} else {
|
||||
// The VM is booting from a disk image that already has the OS installed.
|
||||
// Retrieve the machine identifier and EFI variable store that were saved to
|
||||
// disk during installation.
|
||||
// Retrieve the machine identifier.
|
||||
guard let machineIdentifierData = try? Data(contentsOf: URL(fileURLWithPath: machineIdentifierPath)) else {
|
||||
fatalError("Failed to retrieve the machine identifier data.")
|
||||
}
|
||||
|
||||
guard let machineIdentifier = VZGenericMachineIdentifier(dataRepresentation: machineIdentifierData) else {
|
||||
fatalError("Failed to create the machine identifier.")
|
||||
}
|
||||
|
||||
platform.machineIdentifier = machineIdentifier
|
||||
|
||||
if !FileManager.default.fileExists(atPath: efiVariableStorePath) {
|
||||
fatalError("EFI variable store does not exist.")
|
||||
}
|
||||
|
||||
bootloader.variableStore = VZEFIVariableStore(url: URL(fileURLWithPath: efiVariableStorePath))
|
||||
}
|
||||
|
||||
configuration.platform = platform
|
||||
configuration.bootLoader = bootloader
|
||||
|
||||
|
||||
|
||||
|
||||
// Disk management
|
||||
guard let mainDiskAttachment = try? VZDiskImageStorageDeviceAttachment(url: URL(fileURLWithPath: mainDiskImagePath), readOnly: false) else {
|
||||
fatalError("Failed to create main disk attachment.")
|
||||
}
|
||||
|
||||
let mainDisk = VZVirtioBlockDeviceConfiguration(attachment: mainDiskAttachment)
|
||||
|
||||
disksArray.add(mainDisk)
|
||||
guard let disks = disksArray as? [VZStorageDeviceConfiguration] else {
|
||||
fatalError("Invalid disksArray.")
|
||||
}
|
||||
configuration.storageDevices = disks
|
||||
|
||||
|
||||
// Setup network
|
||||
let networkDevice = VZVirtioNetworkDeviceConfiguration()
|
||||
networkDevice.attachment = VZNATNetworkDeviceAttachment()
|
||||
configuration.networkDevices = [networkDevice]
|
||||
|
||||
// TODO: setup audioDevices
|
||||
|
||||
// Shared dirs
|
||||
let projectsURL = URL(fileURLWithPath: "/Users")
|
||||
|
||||
let sharedDirectory = VZSharedDirectory(url: projectsURL, readOnly: false)
|
||||
let singleDirectoryShare = VZSingleDirectoryShare(directory: sharedDirectory)
|
||||
|
||||
// Create the VZVirtioFileSystemDeviceConfiguration and assign it a unique tag.
|
||||
let sharingConfiguration = VZVirtioFileSystemDeviceConfiguration(tag: "Users")
|
||||
sharingConfiguration.share = singleDirectoryShare
|
||||
configuration.directorySharingDevices = [sharingConfiguration]
|
||||
|
||||
//configuration.serialPorts = [ createConsoleConfiguration() ]
|
||||
//configuration.bootLoader = createBootLoader(kernelURL: kernelURL, initialRamdiskURL: initialRamdiskURL)
|
||||
|
||||
let inputAudioDevice = VZVirtioSoundDeviceConfiguration()
|
||||
|
||||
let inputStream = VZVirtioSoundDeviceInputStreamConfiguration()
|
||||
inputStream.source = VZHostAudioInputStreamSource()
|
||||
|
||||
inputAudioDevice.streams = [inputStream]
|
||||
|
||||
let outputAudioDevice = VZVirtioSoundDeviceConfiguration()
|
||||
|
||||
let outputStream = VZVirtioSoundDeviceOutputStreamConfiguration()
|
||||
outputStream.sink = VZHostAudioOutputStreamSink()
|
||||
|
||||
outputAudioDevice.streams = [outputStream]
|
||||
|
||||
configuration.audioDevices = [inputAudioDevice, outputAudioDevice]
|
||||
|
||||
// configuration.socketDevices = [VZVirtioSocketDeviceConfiguration()]
|
||||
//
|
||||
//
|
||||
do {
|
||||
try configuration.validate()
|
||||
} catch {
|
||||
print("Failed to validate the virtual machine configuration. \(error)")
|
||||
exit(EXIT_FAILURE)
|
||||
}
|
||||
|
||||
// MARK: Instantiate and Start the Virtual Machine
|
||||
|
||||
let virtualMachine = VZVirtualMachine(configuration: configuration)
|
||||
// let socketDevice = virtualMachine.socketDevices[0] as! VZVirtioSocketDevice
|
||||
|
||||
let delegate = Delegate()
|
||||
// let socketListener = VZVirtioSocketListener()
|
||||
// let socketDelegate = MySocketListenerDelegate()
|
||||
// socketListener.delegate = socketDelegate
|
||||
|
||||
background(delay: 3.0, background: {
|
||||
print(shell("/bin/zsh ~/.guix/running-script.sh"))
|
||||
|
||||
}, completion: {
|
||||
|
||||
print("Guix is now running and Graphical apps can be forwarded (if xquartz was installed)")
|
||||
// when background job finishes, wait 3 seconds and do something in main thread
|
||||
})
|
||||
|
||||
|
||||
DispatchQueue.main.async {
|
||||
virtualMachine.delegate = delegate
|
||||
// socketDevice.setSocketListener(socketListener, forPort: 80)
|
||||
|
||||
virtualMachine.start { (result) in
|
||||
if case let .failure(error) = result {
|
||||
print("Failed to start the virtual machine. \(error)")
|
||||
exit(EXIT_FAILURE)
|
||||
}
|
||||
// if case .success() = result {
|
||||
//
|
||||
// sleep(30)
|
||||
//
|
||||
// socketDevice.connect(toPort: 80) { result in
|
||||
// dump(result)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
RunLoop.main.run(until: Date.distantFuture)
|
||||
|
||||
// MARK: - Virtual Machine Delegate
|
||||
|
||||
|
||||
func shell(_ command: String) -> String {
|
||||
let task = Process()
|
||||
let pipe = Pipe()
|
||||
|
||||
task.standardOutput = pipe
|
||||
task.standardError = pipe
|
||||
task.arguments = ["-c", command]
|
||||
task.launchPath = "/bin/zsh"
|
||||
task.standardInput = nil
|
||||
task.launch()
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
let output = String(data: data, encoding: .utf8)!
|
||||
|
||||
return output
|
||||
}
|
||||
func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
background?()
|
||||
if let completion = completion {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
|
||||
completion()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
print("only available on macos 13 or later")
|
||||
}
|
31
README.md
Normal file
31
README.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# MSG (Mac Subsystem for Guix)
|
||||
## Description
|
||||
MSG is an attempt to create a native-like experience for GUIX on MacOS, using methods inspired by others like Podman/Docker/Lima.
|
||||
|
||||
# !!!!Currently only compatible with M1/M2 Macs
|
||||
## README (WIP)
|
||||
|
||||
|
||||
**REQUIREMENTS**
|
||||
- xquartz (if you want to run graphical applications)
|
||||
- You also must go to Xquartz->Settings->Security->Enable 'Allow connections from network clients'
|
||||
- Add the following to your shellrc file (~/.bashrc, ~/.zshrc, etc)
|
||||
- ```
|
||||
alias guix="ssh -i $HOME/.guix/ssh-cert/msg_rsa admin@msg.local 'guix'"
|
||||
alias guix-shell="ssh -i $HOME/.guix/ssh-cert/msg_rsa admin@msg.local"
|
||||
alias guix-env='f(){ ssh -i $HOME/.guix/ssh-cert/msg_rsa admin@msg.local /home/admin/.guix-profile /bin/$@; unset -f f; }; f'
|
||||
alias guix-app='f(){ ssh -X -i $HOME/.guix/ssh-cert/msg_rsa admin@msg.local /home/admin/.guix-profile/bin/$@; unset -f f; }; f'
|
||||
```
|
||||
|
||||
**INSTRUCTIONS**
|
||||
- Drag the Guix.app file into your Applications directory and run!
|
||||
|
||||
**Available Commands (after adding bashrc/zshrc options)**
|
||||
|
||||
* guix : A straight passthrough to the guix application
|
||||
* guix-shell: Connect to the vm over ssh
|
||||
* guix-env : Can be used to pass cli commands interactively
|
||||
* guix-app : Used to passthrough X11 applications from the vm to macos using xquartz
|
||||
|
||||
If you would like to discuss or ask questions, join us on our Discord!
|
||||
https://discord.gg/WSceSUhs6t
|
Loading…
Add table
Reference in a new issue