Add DotNetSdk to simplify using it

This commit is contained in:
Wojciech Figat
2022-12-21 14:13:00 +01:00
parent b049688d31
commit 3f172442be
3 changed files with 180 additions and 96 deletions

View File

@@ -44,44 +44,9 @@ public class nethost : ThirdPartyModule
options.SourceFiles.Clear();
string arch = "x64"; //options.Architecture == TargetArchitecture.x64 ? "x64" : "x86";
string dotnetPath, dotnetVersion;
string appHostRuntimePath;
string os;
string[] dotnetVersions;
// Pick DotNet SDK
if (options.Platform.Target == TargetPlatform.Windows)
{
os = $"win-{arch}";
#pragma warning disable CA1416
using RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
using RegistryKey hostKey = baseKey.OpenSubKey(@$"SOFTWARE\dotnet\Setup\InstalledVersions\{arch}\sharedhost");
dotnetPath = (string)hostKey.GetValue("Path");
using RegistryKey runtimeKey = baseKey.OpenSubKey(@$"SOFTWARE\WOW6432Node\dotnet\Setup\InstalledVersions\{arch}\sharedfx\Microsoft.NETCore.App");
dotnetVersions = runtimeKey.GetValueNames();
#pragma warning restore CA1416
}
else if (options.Platform.Target == TargetPlatform.Linux)
{
// TODO: Support /etc/dotnet/install_location
dotnetPath = "/usr/share/dotnet/";
os = $"linux-{arch}";
dotnetVersions = Directory.GetDirectories($"{dotnetPath}host/fxr/").Select(x => Path.GetFileName(x)).ToArray();
}
else
throw new InvalidPlatformException(options.Platform.Target);
// Pick SDK version
dotnetVersion = dotnetVersions.OrderByDescending(ParseVersion).FirstOrDefault();
if (string.IsNullOrEmpty(dotnetPath))
dotnetPath = Environment.GetEnvironmentVariable("DOTNET_ROOT");
if (string.IsNullOrEmpty(dotnetPath) || string.IsNullOrEmpty(dotnetVersion))
throw new Exception("Failed to find dotnet installation");
int majorVersion = int.Parse(dotnetVersion.Substring(0, dotnetVersion.IndexOf(".")));
if (majorVersion < 7)
throw new Exception($"Unsupported dotnet version found, minimum version required is .NET 7 (found {dotnetVersion})");
var dotnetSdk = DotNetSdk.Instance;
if (!dotnetSdk.IsValid)
throw new Exception($"Missing NET SDK {DotNetSdk.MinimumVersion}.");
// Setup build configuration
switch (options.Platform.Target)
@@ -90,9 +55,8 @@ public class nethost : ThirdPartyModule
case TargetPlatform.XboxOne:
case TargetPlatform.XboxScarlett:
case TargetPlatform.UWP:
appHostRuntimePath = string.Format("{0}packs\\Microsoft.NETCore.App.Host.{1}\\{2}\\runtimes\\{1}\\native", dotnetPath, os, dotnetVersion);
options.OutputFiles.Add(Path.Combine(appHostRuntimePath, "nethost.lib"));
options.DependencyFiles.Add(Path.Combine(appHostRuntimePath, "nethost.dll"));
options.OutputFiles.Add(Path.Combine(dotnetSdk.HostRootPath, "nethost.lib"));
options.DependencyFiles.Add(Path.Combine(dotnetSdk.HostRootPath, "nethost.dll"));
break;
case TargetPlatform.Linux:
case TargetPlatform.Android:
@@ -100,14 +64,13 @@ public class nethost : ThirdPartyModule
case TargetPlatform.PS4:
case TargetPlatform.PS5:
case TargetPlatform.Mac:
appHostRuntimePath = string.Format("{0}packs/Microsoft.NETCore.App.Host.{1}/{2}/runtimes/{1}/native", dotnetPath, os, dotnetVersion);
options.OutputFiles.Add(Path.Combine(appHostRuntimePath, "libnethost.a"));
options.DependencyFiles.Add(Path.Combine(appHostRuntimePath, "libnethost.so"));
options.OutputFiles.Add(Path.Combine(dotnetSdk.HostRootPath, "libnethost.a"));
options.DependencyFiles.Add(Path.Combine(dotnetSdk.HostRootPath, "libnethost.so"));
break;
default:
throw new InvalidPlatformException(options.Platform.Target);
}
options.PublicIncludePaths.Add(appHostRuntimePath);
options.PublicIncludePaths.Add(dotnetSdk.HostRootPath);
options.ScriptingAPI.Defines.Add("USE_NETCORE");
options.DependencyFiles.Add(Path.Combine(FolderPath, "FlaxEngine.CSharp.runtimeconfig.json"));
}

View File

@@ -5,9 +5,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Flax.Build.Graph;
using Flax.Build.Platforms;
using Flax.Deploy;
using Microsoft.Win32;
namespace Flax.Build
{
@@ -148,26 +146,12 @@ namespace Flax.Build
private static void BuildDotNet(TaskGraph graph, BuildData buildData, NativeCpp.BuildOptions buildOptions, string name, List<string> sourceFiles, HashSet<string> fileReferences = null, IGrouping<string, Module> binaryModule = null)
{
#if USE_NETCORE
static Version ParseVersion(string version)
{
// Give precedence to final releases over release candidate / beta releases
int rev = 9999;
if (version.Contains("-")) // e.g. 7.0.0-rc.2.22472.3
{
version = version.Substring(0, version.IndexOf("-"));
rev = 0;
}
Version ver = new Version(version);
return new Version(ver.Major, ver.Minor, ver.Build, rev);
}
#endif
// Setup build options
var buildPlatform = Platform.BuildTargetPlatform;
var outputPath = Path.GetDirectoryName(buildData.Target.GetOutputFilePath(buildOptions));
var outputFile = Path.Combine(outputPath, name + ".dll");
var outputDocFile = Path.Combine(outputPath, name + ".xml");
string monoRoot, monoPath, cscPath, referenceAssemblies, referenceAnalyzers;
string monoRoot, monoPath = null, cscPath, referenceAssemblies, referenceAnalyzers;
switch (buildPlatform)
{
case TargetPlatform.Windows:
@@ -175,28 +159,18 @@ namespace Flax.Build
monoRoot = Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Editor", "Windows", "Mono");
// Prefer installed Roslyn C# compiler over Mono one
monoPath = null;
cscPath = Path.Combine(Path.GetDirectoryName(VCEnvironment.MSBuildPath), "Roslyn", "csc.exe");
#if USE_NETCORE
// dotnet
if (WindowsPlatformBase.TryReadDirRegistryKey(@"HKEY_LOCAL_MACHINE\SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost", "Path", out string dotnetPath))
var dotnetSdk = DotNetSdk.Instance;
if (dotnetSdk.IsValid)
{
#pragma warning disable CA1416
string arch = "x64";
using RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
using RegistryKey sdkVersionsKey = baseKey.OpenSubKey($@"SOFTWARE\WOW6432Node\dotnet\Setup\InstalledVersions\{arch}\sdk");
using RegistryKey sharedfxVersionsKey = baseKey.OpenSubKey($@"SOFTWARE\WOW6432Node\dotnet\Setup\InstalledVersions\{arch}\sharedfx\Microsoft.NETCore.App");
using RegistryKey hostfxrKey = baseKey.OpenSubKey($@"SOFTWARE\WOW6432Node\dotnet\Setup\InstalledVersions\{arch}\hostfxr");
string dotnetSdkVersion = sdkVersionsKey.GetValueNames().OrderByDescending(x => ParseVersion(x)).FirstOrDefault();
string dotnetSharedfxVersion = sharedfxVersionsKey.GetValueNames().OrderByDescending(x => ParseVersion(x)).FirstOrDefault();
#pragma warning restore CA1416
cscPath = @$"{dotnetPath}sdk\{dotnetSdkVersion}\Roslyn\bincore\csc.dll";
referenceAssemblies = @$"{dotnetPath}shared\Microsoft.NETCore.App\{dotnetSharedfxVersion}\";
referenceAnalyzers = @$"{dotnetPath}packs\Microsoft.NETCore.App.Ref\{dotnetSharedfxVersion}\analyzers\dotnet\cs\";
// Use dotnet
cscPath = @$"{dotnetSdk.RootPath}sdk\{dotnetSdk.VersionName}\Roslyn\bincore\csc.dll";
referenceAssemblies = @$"{dotnetSdk.RootPath}shared\Microsoft.NETCore.App\{dotnetSdk.RuntimeVersionName}\";
referenceAnalyzers = @$"{dotnetSdk.RootPath}packs\Microsoft.NETCore.App.Ref\{dotnetSdk.RuntimeVersionName}\analyzers\dotnet\cs\";
}
else //if (!File.Exists(cscPath))
else
#endif
{
// Fallback to Mono binaries
@@ -210,24 +184,13 @@ namespace Flax.Build
case TargetPlatform.Linux:
{
#if USE_NETCORE
// TODO: Support /etc/dotnet/install_location
string dotnetPath = "/usr/share/dotnet/";
string arch = "x64";
string os = $"linux-{arch}";
monoPath = null;
string[] sharedfxVersions = Directory.GetDirectories($"{dotnetPath}shared/Microsoft.NETCore.App/").Select(x => Path.GetFileName(x)).ToArray();
string dotnetSharedfxVersion = sharedfxVersions.OrderByDescending(x => ParseVersion(x)).FirstOrDefault();
string[] sdkVersions = Directory.GetDirectories($"{dotnetPath}sdk/").Select(x => Path.GetFileName(x)).ToArray();
string dotnetSdkVersion = sdkVersions.OrderByDescending(x => ParseVersion(x)).FirstOrDefault();
int majorVersion = int.Parse(dotnetSdkVersion.Substring(0, dotnetSdkVersion.IndexOf(".")));
if (majorVersion >= 7)
var dotnetSdk = DotNetSdk.Instance;
if (dotnetSdk.IsValid)
{
cscPath = @$"{dotnetPath}sdk/{dotnetSdkVersion}/Roslyn/bincore/csc.dll";
referenceAssemblies = @$"{dotnetPath}shared/Microsoft.NETCore.App/{dotnetSharedfxVersion}/";
referenceAnalyzers = @$"{dotnetPath}packs/Microsoft.NETCore.App.Ref/{dotnetSharedfxVersion}/analyzers/dotnet/cs/";
// Use dotnet
cscPath = @$"{dotnetSdk.RootPath}sdk/{dotnetSdk.VersionName}/Roslyn/bincore/csc.dll";
referenceAssemblies = @$"{dotnetSdk.RootPath}shared/Microsoft.NETCore.App/{dotnetSdk.RuntimeVersionName}/";
referenceAnalyzers = @$"{dotnetSdk.RootPath}packs/Microsoft.NETCore.App.Ref/{dotnetSdk.RuntimeVersionName}/analyzers/dotnet/cs/";
}
else
#endif

View File

@@ -0,0 +1,158 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System;
using System.IO;
using System.Linq;
using Microsoft.Win32;
namespace Flax.Build
{
/// <summary>
/// The DotNet SDK.
/// </summary>
public sealed class DotNetSdk : Sdk
{
/// <summary>
/// The singleton instance.
/// </summary>
public static readonly DotNetSdk Instance = new DotNetSdk();
/// <summary>
/// The minimum SDK version.
/// </summary>
public static Version MinimumVersion => new Version(7, 0);
/// <inheritdoc />
public override TargetPlatform[] Platforms
{
get
{
return new[]
{
TargetPlatform.Windows,
TargetPlatform.Linux,
};
}
}
/// <summary>
/// Dotnet SDK version (eg. 7.0).
/// </summary>
public readonly string VersionName;
/// <summary>
/// Dotnet Shared FX library version (eg. 7.0).
/// </summary>
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>
/// Initializes a new instance of the <see cref="DotNetSdk"/> class.
/// </summary>
public DotNetSdk()
{
var platform = Platform.BuildTargetPlatform;
var architecture = Platform.BuildTargetArchitecture;
if (!Platforms.Contains(platform))
return;
// Find system-installed SDK
string dotnetPath;
string os, arch;
string[] dotnetSdkVersions, dotnetRuntimeVersions;
switch (architecture)
{
case TargetArchitecture.x86:
arch = "x86";
break;
case TargetArchitecture.x64:
arch = "x64";
break;
case TargetArchitecture.ARM:
arch = "arm";
break;
case TargetArchitecture.ARM64:
arch = "arm64";
break;
default:
throw new InvalidArchitectureException(architecture);
}
switch (platform)
{
case TargetPlatform.Windows:
{
os = $"win-{arch}";
#pragma warning disable CA1416
using RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
using RegistryKey sdkVersionsKey = baseKey.OpenSubKey($@"SOFTWARE\WOW6432Node\dotnet\Setup\InstalledVersions\{arch}\sdk");
using RegistryKey runtimeKey = baseKey.OpenSubKey(@$"SOFTWARE\WOW6432Node\dotnet\Setup\InstalledVersions\{arch}\sharedfx\Microsoft.NETCore.App");
using RegistryKey hostKey = baseKey.OpenSubKey(@$"SOFTWARE\dotnet\Setup\InstalledVersions\{arch}\sharedhost");
dotnetPath = (string)hostKey.GetValue("Path");
dotnetSdkVersions = sdkVersionsKey.GetValueNames();
dotnetRuntimeVersions = runtimeKey.GetValueNames();
#pragma warning restore CA1416
break;
}
case TargetPlatform.Linux:
{
// TODO: Support /etc/dotnet/install_location
os = $"linux-{arch}";
dotnetPath = "/usr/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:
throw new InvalidPlatformException(platform);
}
// Pick SDK version
string dotnetSdkVersion = dotnetSdkVersions.OrderByDescending(ParseVersion).FirstOrDefault();
string dotnetRuntimeVersion = dotnetRuntimeVersions.OrderByDescending(ParseVersion).FirstOrDefault();
if (string.IsNullOrEmpty(dotnetSdkVersion))
dotnetSdkVersion = Environment.GetEnvironmentVariable("DOTNET_ROOT");
if (string.IsNullOrEmpty(dotnetPath) || string.IsNullOrEmpty(dotnetSdkVersion) || string.IsNullOrEmpty(dotnetRuntimeVersion))
{
Log.Warning("Missing .NET SDK");
return;
}
int majorVersion = int.Parse(dotnetSdkVersion.Substring(0, dotnetSdkVersion.IndexOf(".")));
if (majorVersion < MinimumVersion.Major)
{
Log.Warning($"Unsupported .NET SDK {dotnetSdkVersion} version found. Minimum version required is .NET {MinimumVersion}.");
return;
}
HostRootPath = Path.Combine(dotnetPath, $"packs/Microsoft.NETCore.App.Host.{os}/{dotnetRuntimeVersion}/runtimes/{os}/native");
if (!Directory.Exists(HostRootPath))
{
Log.Warning($"Missing .NET SDK host runtime path in {HostRootPath}.");
return;
}
// Found
RootPath = dotnetPath;
IsValid = true;
Version = ParseVersion(dotnetSdkVersion);
VersionName = dotnetSdkVersion;
RuntimeVersionName = dotnetRuntimeVersion;
Log.Verbose($"Found .NET SDK {VersionName} (runtime {RuntimeVersionName}) at {RootPath}");
}
private static Version ParseVersion(string version)
{
// Give precedence to final releases over release candidate / beta releases
int rev = 9999;
if (version.Contains("-")) // e.g. 7.0.0-rc.2.22472.3
{
version = version.Substring(0, version.IndexOf("-"));
rev = 0;
}
Version ver = new Version(version);
return new Version(ver.Major, ver.Minor, ver.Build, rev);
}
}
}