Add macOS build for dotnet7

This commit is contained in:
Wojtek Figat
2023-02-19 13:31:57 +01:00
parent b44c7ab32c
commit 2c1409c2a4
6 changed files with 75 additions and 26 deletions

View File

@@ -5,7 +5,6 @@ jobs:
# Editor # Editor
editor-mac: editor-mac:
if: ${{ false }}
name: Editor (Mac, Development x64) name: Editor (Mac, Development x64)
runs-on: "macos-latest" runs-on: "macos-latest"
steps: steps:
@@ -30,7 +29,6 @@ jobs:
# Game # Game
game-mac: game-mac:
if: ${{ false }}
name: Game (Mac, Release x64) name: Game (Mac, Release x64)
runs-on: "macos-latest" runs-on: "macos-latest"
steps: steps:

View File

@@ -59,7 +59,13 @@ bool CoreCLR::InitHostfxr(const String& configPath, const String& libraryPath)
const String path(hostfxrPath); const String path(hostfxrPath);
LOG(Info, "Found hostfxr in {0}", path); LOG(Info, "Found hostfxr in {0}", path);
// Get API from hostfxr library
void* hostfxr = Platform::LoadLibrary(path.Get()); void* hostfxr = Platform::LoadLibrary(path.Get());
if (hostfxr == nullptr)
{
LOG(Error, "Failed to setup hostfxr API ({0})", path);
return true;
}
hostfxr_initialize_for_runtime_config = (hostfxr_initialize_for_runtime_config_fn)Platform::GetProcAddress(hostfxr, "hostfxr_initialize_for_runtime_config"); hostfxr_initialize_for_runtime_config = (hostfxr_initialize_for_runtime_config_fn)Platform::GetProcAddress(hostfxr, "hostfxr_initialize_for_runtime_config");
hostfxr_initialize_for_dotnet_command_line = (hostfxr_initialize_for_dotnet_command_line_fn)Platform::GetProcAddress(hostfxr, "hostfxr_initialize_for_dotnet_command_line"); hostfxr_initialize_for_dotnet_command_line = (hostfxr_initialize_for_dotnet_command_line_fn)Platform::GetProcAddress(hostfxr, "hostfxr_initialize_for_dotnet_command_line");
hostfxr_get_runtime_delegate = (hostfxr_get_runtime_delegate_fn)Platform::GetProcAddress(hostfxr, "hostfxr_get_runtime_delegate"); hostfxr_get_runtime_delegate = (hostfxr_get_runtime_delegate_fn)Platform::GetProcAddress(hostfxr, "hostfxr_get_runtime_delegate");
@@ -69,7 +75,7 @@ bool CoreCLR::InitHostfxr(const String& configPath, const String& libraryPath)
hostfxr_run_app = (hostfxr_run_app_fn)Platform::GetProcAddress(hostfxr, "hostfxr_run_app"); hostfxr_run_app = (hostfxr_run_app_fn)Platform::GetProcAddress(hostfxr, "hostfxr_run_app");
if (!hostfxr_get_runtime_delegate || !hostfxr_run_app) if (!hostfxr_get_runtime_delegate || !hostfxr_run_app)
{ {
LOG(Error, "Failed to setup hostfxr API"); LOG(Error, "Failed to setup hostfxr API ({0})", path);
return true; return true;
} }

View File

@@ -119,6 +119,7 @@ void MCore::UnloadDomain(const MString& domainName)
#if USE_NETCORE #if USE_NETCORE
bool MCore::LoadEngine() bool MCore::LoadEngine()
{ {
PROFILE_CPU();
const String csharpLibraryPath = Globals::BinariesFolder / TEXT("FlaxEngine.CSharp.dll"); const String csharpLibraryPath = Globals::BinariesFolder / TEXT("FlaxEngine.CSharp.dll");
const String csharpRuntimeConfigPath = Globals::BinariesFolder / TEXT("FlaxEngine.CSharp.runtimeconfig.json"); const String csharpRuntimeConfigPath = Globals::BinariesFolder / TEXT("FlaxEngine.CSharp.runtimeconfig.json");
if (!FileSystem::FileExists(csharpLibraryPath)) if (!FileSystem::FileExists(csharpLibraryPath))
@@ -152,6 +153,9 @@ bool MCore::LoadEngine()
void MCore::UnloadEngine() void MCore::UnloadEngine()
{ {
if (!MRootDomain)
return;
PROFILE_CPU();
CoreCLR::CallStaticMethodByName<void>(TEXT("Exit")); CoreCLR::CallStaticMethodByName<void>(TEXT("Exit"));
MDomains.ClearDelete(); MDomains.ClearDelete();
MRootDomain = nullptr; MRootDomain = nullptr;

View File

@@ -140,7 +140,7 @@ bool ScriptingService::Init()
// Initialize managed runtime // Initialize managed runtime
if (MCore::LoadEngine()) if (MCore::LoadEngine())
{ {
LOG(Fatal, "Mono initialization failed."); LOG(Fatal, "C# runtime initialization failed.");
return true; return true;
} }

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.IO;
using System; using System;
using System.IO;
using Flax.Build; using Flax.Build;
using Flax.Build.NativeCpp; using Flax.Build.NativeCpp;
@@ -29,9 +29,12 @@ public class nethost : ThirdPartyModule
options.SourceFiles.Clear(); options.SourceFiles.Clear();
// Get .NET SDK runtime host
var dotnetSdk = DotNetSdk.Instance; var dotnetSdk = DotNetSdk.Instance;
if (!dotnetSdk.IsValid) if (!dotnetSdk.IsValid)
throw new Exception($"Missing NET SDK {DotNetSdk.MinimumVersion}."); throw new Exception($"Missing NET SDK {DotNetSdk.MinimumVersion}.");
if (!dotnetSdk.GetHostRuntime(options.Platform.Target, options.Architecture, out var hostRuntimePath))
throw new Exception($"Missing NET SDK runtime for {options.Platform.Target} {options.Architecture}.");
// Setup build configuration // Setup build configuration
switch (options.Platform.Target) switch (options.Platform.Target)
@@ -40,22 +43,25 @@ public class nethost : ThirdPartyModule
case TargetPlatform.XboxOne: case TargetPlatform.XboxOne:
case TargetPlatform.XboxScarlett: case TargetPlatform.XboxScarlett:
case TargetPlatform.UWP: case TargetPlatform.UWP:
options.OutputFiles.Add(Path.Combine(dotnetSdk.HostRootPath, "nethost.lib")); options.OutputFiles.Add(Path.Combine(hostRuntimePath, "nethost.lib"));
options.DependencyFiles.Add(Path.Combine(dotnetSdk.HostRootPath, "nethost.dll")); options.DependencyFiles.Add(Path.Combine(hostRuntimePath, "nethost.dll"));
break; break;
case TargetPlatform.Linux: case TargetPlatform.Linux:
case TargetPlatform.Android: case TargetPlatform.Android:
case TargetPlatform.Switch: case TargetPlatform.Switch:
case TargetPlatform.PS4: case TargetPlatform.PS4:
case TargetPlatform.PS5: case TargetPlatform.PS5:
options.OutputFiles.Add(Path.Combine(hostRuntimePath, "libnethost.a"));
options.DependencyFiles.Add(Path.Combine(hostRuntimePath, "libnethost.so"));
break;
case TargetPlatform.Mac: case TargetPlatform.Mac:
options.OutputFiles.Add(Path.Combine(dotnetSdk.HostRootPath, "libnethost.a")); options.OutputFiles.Add(Path.Combine(hostRuntimePath, "libnethost.a"));
options.DependencyFiles.Add(Path.Combine(dotnetSdk.HostRootPath, "libnethost.so")); options.DependencyFiles.Add(Path.Combine(hostRuntimePath, "libnethost.dylib"));
break; break;
default: default:
throw new InvalidPlatformException(options.Platform.Target); throw new InvalidPlatformException(options.Platform.Target);
} }
options.PublicIncludePaths.Add(dotnetSdk.HostRootPath); options.PublicIncludePaths.Add(hostRuntimePath);
options.ScriptingAPI.Defines.Add("USE_NETCORE"); options.ScriptingAPI.Defines.Add("USE_NETCORE");
options.DependencyFiles.Add(Path.Combine(FolderPath, "FlaxEngine.CSharp.runtimeconfig.json")); options.DependencyFiles.Add(Path.Combine(FolderPath, "FlaxEngine.CSharp.runtimeconfig.json"));
} }

View File

@@ -3,6 +3,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Collections.Generic;
using Microsoft.Win32; using Microsoft.Win32;
namespace Flax.Build namespace Flax.Build
@@ -12,6 +13,8 @@ namespace Flax.Build
/// </summary> /// </summary>
public sealed class DotNetSdk : Sdk public sealed class DotNetSdk : Sdk
{ {
private Dictionary<KeyValuePair<TargetPlatform, TargetArchitecture>, string> _hostRuntimes = new();
/// <summary> /// <summary>
/// The singleton instance. /// The singleton instance.
/// </summary> /// </summary>
@@ -31,6 +34,7 @@ namespace Flax.Build
{ {
TargetPlatform.Windows, TargetPlatform.Windows,
TargetPlatform.Linux, TargetPlatform.Linux,
TargetPlatform.Mac,
}; };
} }
} }
@@ -45,11 +49,6 @@ namespace Flax.Build
/// </summary> /// </summary>
public readonly string RuntimeVersionName; public readonly string RuntimeVersionName;
/// <summary>
/// Dotnet hosting library files path (eg. <RootPath>/packs/Microsoft.NETCore.App.Host.<os>/<VersionName>/runtimes/<os>-<arcg>/native).
/// </summary>
public readonly string HostRootPath;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DotNetSdk"/> class. /// Initializes a new instance of the <see cref="DotNetSdk"/> class.
/// </summary> /// </summary>
@@ -114,6 +113,15 @@ namespace Flax.Build
dotnetRuntimeVersions = Directory.GetDirectories($"{dotnetPath}shared/Microsoft.NETCore.App/").Select(Path.GetFileName).ToArray(); dotnetRuntimeVersions = Directory.GetDirectories($"{dotnetPath}shared/Microsoft.NETCore.App/").Select(Path.GetFileName).ToArray();
break; break;
} }
case TargetPlatform.Mac:
{
rid = $"osx-{arch}";
ridFallback = "";
dotnetPath = "/usr/local/share/dotnet/";
dotnetSdkVersions = Directory.GetDirectories($"{dotnetPath}sdk/").Select(Path.GetFileName).ToArray();
dotnetRuntimeVersions = Directory.GetDirectories($"{dotnetPath}shared/Microsoft.NETCore.App/").Select(Path.GetFileName).ToArray();
break;
}
default: default:
throw new InvalidPlatformException(platform); throw new InvalidPlatformException(platform);
} }
@@ -134,22 +142,49 @@ namespace Flax.Build
Log.Warning($"Unsupported .NET SDK {dotnetSdkVersion} version found. Minimum version required is .NET {MinimumVersion}."); Log.Warning($"Unsupported .NET SDK {dotnetSdkVersion} version found. Minimum version required is .NET {MinimumVersion}.");
return; return;
} }
HostRootPath = Path.Combine(dotnetPath, $"packs/Microsoft.NETCore.App.Host.{rid}/{dotnetRuntimeVersion}/runtimes/{rid}/native");
if (!string.IsNullOrEmpty(ridFallback) && !Directory.Exists(HostRootPath))
HostRootPath = Path.Combine(dotnetPath, $"packs/Microsoft.NETCore.App.Host.{ridFallback}/{dotnetRuntimeVersion}/runtimes/{ridFallback}/native");
if (!Directory.Exists(HostRootPath))
{
Log.Warning($"Missing .NET SDK host runtime path in {HostRootPath}.");
return;
}
// Found
RootPath = dotnetPath; RootPath = dotnetPath;
IsValid = true;
Version = ParseVersion(dotnetSdkVersion); Version = ParseVersion(dotnetSdkVersion);
VersionName = dotnetSdkVersion; VersionName = dotnetSdkVersion;
RuntimeVersionName = dotnetRuntimeVersion; RuntimeVersionName = dotnetRuntimeVersion;
// Pick SDK runtime
if (!TryAddHostRuntime(platform, architecture, rid) && !TryAddHostRuntime(platform, architecture, ridFallback))
{
var path = Path.Combine(RootPath, $"packs/Microsoft.NETCore.App.Host.{rid}/{RuntimeVersionName}/runtimes/{rid}/native");
Log.Warning($"Missing .NET SDK host runtime for {platform} {architecture} ({path}).");
return;
}
TryAddHostRuntime(TargetPlatform.Windows, TargetArchitecture.x86, "win-x86");
TryAddHostRuntime(TargetPlatform.Windows, TargetArchitecture.x64, "win-x64");
TryAddHostRuntime(TargetPlatform.Windows, TargetArchitecture.ARM64, "win-arm64");
TryAddHostRuntime(TargetPlatform.Mac, TargetArchitecture.x64, "osx-x64");
TryAddHostRuntime(TargetPlatform.Mac, TargetArchitecture.ARM64, "osx-arm64");
// Found
IsValid = true;
Log.Verbose($"Found .NET SDK {VersionName} (runtime {RuntimeVersionName}) at {RootPath}"); Log.Verbose($"Found .NET SDK {VersionName} (runtime {RuntimeVersionName}) at {RootPath}");
foreach (var e in _hostRuntimes)
Log.Verbose($" - Host Runtime for {e.Key.Key} {e.Key.Value}");
}
/// <summary>
/// Gets the path to runtime host contents folder for a given target platform and architecure.
/// In format: <RootPath>/packs/Microsoft.NETCore.App.Host.<os>/<VersionName>/runtimes/<os>-<arch>/native
/// </summary>
public bool GetHostRuntime(TargetPlatform platform, TargetArchitecture arch, out string path)
{
return _hostRuntimes.TryGetValue(new KeyValuePair<TargetPlatform, TargetArchitecture>(platform, arch), out path);
}
private bool TryAddHostRuntime(TargetPlatform platform, TargetArchitecture arch, string rid)
{
if (string.IsNullOrEmpty(rid))
return false;
var path = Path.Combine(RootPath, $"packs/Microsoft.NETCore.App.Host.{rid}/{RuntimeVersionName}/runtimes/{rid}/native");
var exists = Directory.Exists(path);
if (exists)
_hostRuntimes[new KeyValuePair<TargetPlatform, TargetArchitecture>(platform, arch)] = path;
return exists;
} }
private static Version ParseVersion(string version) private static Version ParseVersion(string version)