Add nethost module and EngineConfiguration for .NET runtime

This commit is contained in:
2022-07-08 14:14:33 +03:00
parent cb09fb570d
commit c4be764f61
11 changed files with 249 additions and 28 deletions

View File

@@ -11,6 +11,7 @@
"EditorTarget": "FlaxEditor",
"Configuration": {
"UseCSharp": true,
"UseLargeWorlds": false
"UseLargeWorlds": false,
"UseDotNet": true
}
}

View File

@@ -15,7 +15,10 @@ public class Scripting : EngineModule
if (EngineConfiguration.WithCSharp(options))
{
options.PublicDependencies.Add("mono");
if (EngineConfiguration.UseDotNet)
options.PublicDependencies.Add("nethost");
else
options.PublicDependencies.Add("mono");
}
options.PrivateDependencies.Add("Utilities");

View File

@@ -0,0 +1,9 @@
{
"runtimeOptions": {
"tfm": "net7.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "7.0.0-rc.2.22472.3"
}
}
}

23
Source/ThirdParty/nethost/LICENSE.TXT vendored Normal file
View File

@@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright (c) .NET Foundation and Contributors
All rights reserved.
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.

View File

@@ -0,0 +1,92 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using System.IO;
using System;
using Flax.Build;
using Flax.Build.NativeCpp;
using Flax.Build.Platforms;
using Microsoft.Win32;
using System.Linq;
/// <summary>
/// Module for nethost (.NET runtime host library)
/// </summary>
public class nethost : ThirdPartyModule
{
/// <inheritdoc />
public override void Init()
{
base.Init();
LicenseType = LicenseTypes.MIT;
LicenseFilePath = "LICENSE.TXT";
// Merge third-party modules into engine binary
BinaryModuleName = "FlaxEngine";
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
public override void Setup(BuildOptions options)
{
base.Setup(options);
options.SourceFiles.Clear();
string appHostRuntimePath;
if (options.Platform.Target == TargetPlatform.Windows)
{
// NOTE: nethost is bundled with SDK, not runtime. Should C# scripting have a hard requirement for SDK to be installed?
string arch = "x64"; //options.Architecture == TargetArchitecture.x64 ? "x64" : "x86";
using RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
using RegistryKey hostKey = baseKey.OpenSubKey(@$"SOFTWARE\dotnet\Setup\InstalledVersions\{arch}\sharedhost");
string dotnetPath = (string)hostKey.GetValue("Path");
using RegistryKey runtimeKey = baseKey.OpenSubKey(@$"SOFTWARE\WOW6432Node\dotnet\Setup\InstalledVersions\{arch}\sharedfx\Microsoft.NETCore.App");
string[] versions = runtimeKey.GetValueNames();
string dotnetVersion = versions.OrderByDescending(x => ParseVersion(x)).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})");
appHostRuntimePath = String.Format("{0}packs\\Microsoft.NETCore.App.Host.win-{1}\\{2}\\runtimes\\win-{1}\\native", dotnetPath, arch, dotnetVersion);
options.OutputFiles.Add(Path.Combine(appHostRuntimePath, "nethost.lib"));
options.DependencyFiles.Add(Path.Combine(appHostRuntimePath, "nethost.dll"));
options.PublicIncludePaths.Add(appHostRuntimePath);
}
else
{
// /etc/dotnet/install_location
throw new InvalidPlatformException(options.Platform.Target);
}
options.PublicIncludePaths.Add(appHostRuntimePath);
options.ScriptingAPI.Defines.Add("USE_NETCORE");
options.DependencyFiles.Add(Path.Combine(FolderPath, "FlaxEngine.CSharp.runtimeconfig.json"));
}
}

View File

@@ -5,7 +5,9 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Flax.Build.Graph;
using Flax.Build.Platforms;
using Flax.Deploy;
using Microsoft.Win32;
using Task = Flax.Build.Graph.Task;
namespace Flax.Build
@@ -152,7 +154,7 @@ namespace Flax.Build
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;
string monoRoot, monoPath, cscPath, referenceAssemblies, referenceAnalyzers;
switch (buildPlatform)
{
case TargetPlatform.Windows:
@@ -163,11 +165,43 @@ namespace Flax.Build
monoPath = null;
cscPath = Path.Combine(Path.GetDirectoryName(VCEnvironment.MSBuildPath), "Roslyn", "csc.exe");
if (!File.Exists(cscPath))
// dotnet
if (WindowsPlatformBase.TryReadDirRegistryKey(@"HKEY_LOCAL_MACHINE\SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost", "Path", out string dotnetPath))
{
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);
}
#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();
string dotnetHostfxrVersion = (string)hostfxrKey.GetValue("Version");
#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\";
}
else //if (!File.Exists(cscPath))
{
// Fallback to Mono binaries
monoPath = Path.Combine(monoRoot, "bin", "mono.exe");
cscPath = Path.Combine(monoRoot, "lib", "mono", "4.5", "csc.exe");
referenceAssemblies = Path.Combine(monoRoot, "lib", "mono", "4.5-api");
referenceAnalyzers = "";
}
break;
}
@@ -175,15 +209,19 @@ namespace Flax.Build
monoRoot = Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Editor", "Linux", "Mono");
monoPath = Path.Combine(monoRoot, "bin", "mono");
cscPath = Path.Combine(monoRoot, "lib", "mono", "4.5", "csc.exe");
referenceAssemblies = Path.Combine(monoRoot, "lib", "mono", "4.5-api");
referenceAnalyzers = "";
break;
case TargetPlatform.Mac:
monoRoot = Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Editor", "Mac", "Mono");
monoPath = Path.Combine(monoRoot, "bin", "mono");
cscPath = Path.Combine(monoRoot, "lib", "mono", "4.5", "csc.exe");
referenceAssemblies = Path.Combine(monoRoot, "lib", "mono", "4.5-api");
referenceAnalyzers = "";
break;
default: throw new InvalidPlatformException(buildPlatform);
}
var referenceAssemblies = Path.Combine(monoRoot, "lib", "mono", "4.5-api");
if (fileReferences == null)
fileReferences = buildOptions.ScriptingAPI.FileReferences;
else
@@ -207,9 +245,11 @@ namespace Flax.Build
args.Add("/warn:4");
args.Add("/unsafe");
args.Add("/fullpaths");
args.Add("/langversion:7.3");
args.Add("/filealign:512");
args.Add("/langversion:latest");
if (buildOptions.ScriptingAPI.IgnoreMissingDocumentationWarnings)
args.Add("-nowarn:1591");
args.Add("-nowarn:8632"); // nullable
args.Add(buildData.Configuration == TargetConfiguration.Debug ? "/optimize-" : "/optimize+");
args.Add(string.Format("/out:\"{0}\"", outputFile));
args.Add(string.Format("/doc:\"{0}\"", outputDocFile));
@@ -217,11 +257,13 @@ namespace Flax.Build
args.Add("/define:" + string.Join(";", buildOptions.ScriptingAPI.Defines));
if (buildData.Configuration == TargetConfiguration.Debug)
args.Add("/define:DEBUG");
args.Add(string.Format("/reference:\"{0}{1}mscorlib.dll\"", referenceAssemblies, Path.DirectorySeparatorChar));
args.Add(string.Format("/reference:\"{0}mscorlib.dll\"", referenceAssemblies));
foreach (var reference in buildOptions.ScriptingAPI.SystemReferences)
args.Add(string.Format("/reference:\"{0}{2}{1}.dll\"", referenceAssemblies, reference, Path.DirectorySeparatorChar));
args.Add(string.Format("/reference:\"{0}{1}.dll\"", referenceAssemblies, reference));
foreach (var reference in fileReferences)
args.Add(string.Format("/reference:\"{0}\"", reference));
foreach (var analyzer in buildOptions.ScriptingAPI.SystemAnalyzers)
args.Add(string.Format("/analyzer:\"{0}{1}.dll\"", referenceAnalyzers, analyzer));
foreach (var sourceFile in sourceFiles)
args.Add("\"" + sourceFile + "\"");
@@ -249,8 +291,8 @@ namespace Flax.Build
// The "/shared" flag enables the compiler server support:
// https://github.com/dotnet/roslyn/blob/main/docs/compilers/Compiler%20Server.md
task.CommandPath = cscPath;
task.CommandArguments = $"/noconfig /shared @\"{responseFile}\"";
task.CommandPath = "dotnet.exe";
task.CommandArguments = $"exec \"{cscPath}\" /noconfig /shared @\"{responseFile}\"";
}
BuildDotNetAssembly?.Invoke(graph, buildData, buildOptions, task, binaryModule);

View File

@@ -156,6 +156,11 @@ namespace Flax.Build.NativeCpp
/// </summary>
public HashSet<string> FileReferences;
/// <summary>
/// The .Net libraries references (dll or exe files paths).
/// </summary>
public HashSet<string> SystemAnalyzers;
/// <summary>
/// True if ignore compilation warnings due to missing code documentation comments.
/// </summary>
@@ -182,9 +187,53 @@ namespace Flax.Build.NativeCpp
Defines = new HashSet<string>(),
SystemReferences = new HashSet<string>
{
"Microsoft.CSharp",
"System",
"System.Xml",
"System.Collections",
"System.Collections.Concurrent",
"System.Collections.NonGeneric",
"System.Collections.Specialized",
"System.Collections.Immutable",
"System.ComponentModel",
"System.ComponentModel.DataAnnotations",
"System.ComponentModel.Primitives",
"System.ComponentModel.TypeConverter",
"System.Console",
"System.Core",
"System.Globalization",
"System.IO",
"System.IO.Compression",
"System.IO.FileSystem.Watcher",
"System.Linq",
"System.Linq.Expressions",
"System.Net.Http",
"System.Net.Primitives",
"System.ObjectModel",
"System.Private.CoreLib",
"System.Private.Uri",
"System.Private.Xml",
"System.Reflection",
"System.Runtime",
"System.Runtime.CompilerServices.Unsafe",
"System.Runtime.InteropServices",
"System.Runtime.InteropServices.RuntimeInformation",
"System.Runtime.Serialization.Formatters", // BinaryFormatter
"System.Security.Cryptography",
"System.Security.Cryptography.Algorithms",
"System.Security.Cryptography.Primitives",
"System.Text.RegularExpressions",
"System.Threading.Tasks.Parallel",
"System.Xml",
"System.Reflection.Metadata",
"netstandard",
},
SystemAnalyzers = new HashSet<string>
{
@"Microsoft.Interop.LibraryImportGenerator",
@"Microsoft.Interop.SourceGeneration",
},
FileReferences = new HashSet<string>(),
};

View File

@@ -242,6 +242,12 @@ namespace Flax.Build
[CommandLine("useCSharp", "0 to disable C# support in build")]
public static bool UseCSharp = true;
/// <summary>
/// True if .NET support should be enabled.
/// </summary>
[CommandLine("useDotNet", "1 to enable .NET support in build, 0 to enable Mono support in build")]
public static bool UseDotNet = true;
public static bool WithCSharp(NativeCpp.BuildOptions options)
{
if (options.Platform.Target == TargetPlatform.PS5)
@@ -254,5 +260,10 @@ namespace Flax.Build
// This can be used to selectively control 64-bit coordinates per-platform or build configuration
return UseLargeWorlds;
}
public static bool WithDotNet(NativeCpp.BuildOptions options)
{
return UseDotNet;
}
}
}

View File

@@ -9,6 +9,8 @@ using Flax.Build.Platforms;
using Flax.Build.Projects.VisualStudio;
using Microsoft.Win32;
#pragma warning disable CA1416
namespace Flax.Deploy
{
/// <summary>
@@ -286,3 +288,5 @@ namespace Flax.Deploy
}
}
}
#pragma warning restore CA1416

View File

@@ -11,6 +11,8 @@ using Flax.Build.Projects.VisualStudio;
using Flax.Build.Projects.VisualStudioCode;
using Microsoft.Win32;
#pragma warning disable CA1416
namespace Flax.Build.Platforms
{
/// <summary>
@@ -523,3 +525,5 @@ namespace Flax.Build.Platforms
}
}
}
#pragma warning restore CA1416

View File

@@ -1,17 +0,0 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Flax.Build")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Wojciech Figat")]
[assembly: AssemblyProduct("Flax.Build")]
[assembly: AssemblyCopyright("Copyright © 2012-2022 Wojciech Figat")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("c99aaf92-d4ad-4847-9ee0-b11e68e93e1e")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]