From 0c4a608b654fc02f7f750fe844d472065055afdc Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 4 Apr 2023 14:46:08 +0200 Subject: [PATCH] Add .NET 7 support to Xbox --- .../Cooker/Platform/GDK/GDKPlatformTools.cpp | 96 ------------------- .../Cooker/Platform/GDK/GDKPlatformTools.h | 3 - Source/ThirdParty/nethost/nethost.Build.cs | 2 +- .../Flax.Build/Build/DotNet/DotNetAOT.cs | 32 ++----- .../Flax.Build/Build/DotNet/DotNetSdk.cs | 10 ++ Source/Tools/Flax.Build/Build/Toolchain.cs | 22 +++++ .../Platforms/Windows/WindowsToolchainBase.cs | 26 +++++ 7 files changed, 68 insertions(+), 123 deletions(-) diff --git a/Source/Editor/Cooker/Platform/GDK/GDKPlatformTools.cpp b/Source/Editor/Cooker/Platform/GDK/GDKPlatformTools.cpp index 28032ad07..e28a711ac 100644 --- a/Source/Editor/Cooker/Platform/GDK/GDKPlatformTools.cpp +++ b/Source/Editor/Cooker/Platform/GDK/GDKPlatformTools.cpp @@ -42,21 +42,6 @@ DotNetAOTModes GDKPlatformTools::UseAOT() const return DotNetAOTModes::MonoAOTDynamic; } -bool GDKPlatformTools::OnScriptsStepDone(CookingData& data) -{ - // Override Newtonsoft.Json.dll for some platforms (that don't support runtime code generation) - const String customBinPath = data.GetPlatformBinariesRoot() / TEXT("Newtonsoft.Json.dll"); - const String assembliesPath = data.ManagedCodeOutputPath; - if (FileSystem::CopyFile(assembliesPath / TEXT("Newtonsoft.Json.dll"), customBinPath)) - { - data.Error(TEXT("Failed to copy deloy custom assembly.")); - return true; - } - FileSystem::DeleteFile(assembliesPath / TEXT("Newtonsoft.Json.pdb")); - - return false; -} - bool GDKPlatformTools::OnDeployBinaries(CookingData& data) { // Copy binaries @@ -83,87 +68,6 @@ bool GDKPlatformTools::OnDeployBinaries(CookingData& data) return false; } -void GDKPlatformTools::OnConfigureAOT(CookingData& data, AotConfig& config) -{ - const auto platformDataPath = data.GetPlatformBinariesRoot(); - const bool useInterpreter = true; // TODO: use Full AOT on GDK - const bool enableDebug = data.Configuration != BuildConfiguration::Release; - const Char* aotMode = useInterpreter ? TEXT("full,interp") : TEXT("full"); - const Char* debugMode = enableDebug ? TEXT("soft-debug") : TEXT("nodebug"); - config.AotCompilerArgs = String::Format(TEXT("--aot={0},verbose,stats,print-skipped,{1} -O=all"), aotMode, debugMode); - if (enableDebug) - config.AotCompilerArgs = TEXT("--debug ") + config.AotCompilerArgs; - config.AotCompilerPath = platformDataPath / TEXT("Tools/mono.exe"); -} - -bool GDKPlatformTools::OnPerformAOT(CookingData& data, AotConfig& config, const String& assemblyPath) -{ - // Skip .dll.dll which could be a false result from the previous AOT which could fail - if (assemblyPath.EndsWith(TEXT(".dll.dll"))) - { - LOG(Warning, "Skip AOT for file '{0}' as it can be a result from the previous task", assemblyPath); - return false; - } - - // Check if skip this assembly (could be already processed) - const String filename = StringUtils::GetFileName(assemblyPath); - const String outputPath = config.AotCachePath / filename + TEXT(".dll"); - if (FileSystem::FileExists(outputPath) && FileSystem::GetFileLastEditTime(assemblyPath) < FileSystem::GetFileLastEditTime(outputPath)) - return false; - LOG(Info, "Calling AOT tool for \"{0}\"", assemblyPath); - - // Cleanup temporary results (fromm the previous AT that fail or sth) - const String resultPath = assemblyPath + TEXT(".dll"); - const String resultPathExp = resultPath + TEXT(".exp"); - const String resultPathLib = resultPath + TEXT(".lib"); - const String resultPathPdb = resultPath + TEXT(".pdb"); - if (FileSystem::FileExists(resultPath)) - FileSystem::DeleteFile(resultPath); - if (FileSystem::FileExists(resultPathExp)) - FileSystem::DeleteFile(resultPathExp); - if (FileSystem::FileExists(resultPathLib)) - FileSystem::DeleteFile(resultPathLib); - if (FileSystem::FileExists(resultPathPdb)) - FileSystem::DeleteFile(resultPathPdb); - - // Call tool - CreateProcessSettings procSettings; - procSettings.FileName = String::Format(TEXT("\"{0}\" {1} \"{2}\""), config.AotCompilerPath, config.AotCompilerArgs, assemblyPath); - procSettings.WorkingDirectory = StringUtils::GetDirectoryName(config.AotCompilerPath); - procSettings.Environment = config.EnvVars; - const int32 result = Platform::CreateProcess(procSettings); - if (result != 0) - { - data.Error(TEXT("AOT tool execution failed with result code {1} for assembly \"{0}\". See log for more info."), assemblyPath, result); - return true; - } - - // Copy result - if (FileSystem::CopyFile(outputPath, resultPath)) - { - data.Error(TEXT("Failed to copy the AOT tool result file. It can be missing.")); - return true; - } - - // Copy pdb file if exists - if (data.Configuration != BuildConfiguration::Release && FileSystem::FileExists(resultPathPdb)) - { - FileSystem::CopyFile(config.AotCachePath / StringUtils::GetFileName(resultPathPdb), resultPathPdb); - } - - // Clean intermediate results - if (FileSystem::DeleteFile(resultPath) - || (FileSystem::FileExists(resultPathExp) && FileSystem::DeleteFile(resultPathExp)) - || (FileSystem::FileExists(resultPathLib) && FileSystem::DeleteFile(resultPathLib)) - || (FileSystem::FileExists(resultPathPdb) && FileSystem::DeleteFile(resultPathPdb)) - ) - { - LOG(Warning, "Failed to remove the AOT tool result file(s)."); - } - - return false; -} - bool GDKPlatformTools::OnPostProcess(CookingData& data, GDKPlatformSettings* platformSettings) { // Configuration diff --git a/Source/Editor/Cooker/Platform/GDK/GDKPlatformTools.h b/Source/Editor/Cooker/Platform/GDK/GDKPlatformTools.h index 6f4a138a8..284098ec9 100644 --- a/Source/Editor/Cooker/Platform/GDK/GDKPlatformTools.h +++ b/Source/Editor/Cooker/Platform/GDK/GDKPlatformTools.h @@ -27,10 +27,7 @@ public: // [PlatformTools] DotNetAOTModes UseAOT() const override; - bool OnScriptsStepDone(CookingData& data) override; bool OnDeployBinaries(CookingData& data) override; - void OnConfigureAOT(CookingData& data, AotConfig& config) override; - bool OnPerformAOT(CookingData& data, AotConfig& config, const String& assemblyPath) override; }; #endif diff --git a/Source/ThirdParty/nethost/nethost.Build.cs b/Source/ThirdParty/nethost/nethost.Build.cs index fbe3044dc..97cab0e54 100644 --- a/Source/ThirdParty/nethost/nethost.Build.cs +++ b/Source/ThirdParty/nethost/nethost.Build.cs @@ -54,7 +54,7 @@ public class nethost : ThirdPartyModule options.OutputFiles.Add(Path.Combine(hostRuntime.Path, "nethost.lib")); options.DependencyFiles.Add(Path.Combine(hostRuntime.Path, "nethost.dll")); } - else + else if (hostRuntime.Type == DotNetSdk.HostType.Mono) { options.PublicDefinitions.Add("USE_MONO_DYNAMIC_LIB"); options.OutputFiles.Add(Path.Combine(hostRuntime.Path, "coreclr.import.lib")); diff --git a/Source/Tools/Flax.Build/Build/DotNet/DotNetAOT.cs b/Source/Tools/Flax.Build/Build/DotNet/DotNetAOT.cs index 1613226d9..ccd913bf9 100644 --- a/Source/Tools/Flax.Build/Build/DotNet/DotNetAOT.cs +++ b/Source/Tools/Flax.Build/Build/DotNet/DotNetAOT.cs @@ -304,14 +304,9 @@ namespace Flax.Build } else if (aotMode == DotNetAOTModes.MonoAOTDynamic || aotMode == DotNetAOTModes.MonoAOTStatic) { - var platformToolsRoot = Path.Combine(Globals.EngineRoot, "Source/Platforms", platform.ToString(), "Binaries/Tools"); - if (!Directory.Exists(platformToolsRoot)) - throw new Exception("Missing platform tools " + platformToolsRoot); var dotnetLibPath = Path.Combine(aotAssembliesPath, "lib/net7.0"); var monoAssembliesOutputPath = aotMode == DotNetAOTModes.MonoAOTDynamic ? dotnetOutputPath : null; - // TODO: impl Mono AOT more generic way, not just Windows-only case - // Build list of assemblies to process (use game assemblies as root to walk over used references from stdlib) var assembliesPaths = new List(); if (Configuration.SkipUnusedDotnetLibsPackaging) @@ -371,25 +366,16 @@ namespace Flax.Build Log.Info(""); Log.Info(""); } - - // Setup options - var aotCompilerPath = Path.Combine(platformToolsRoot, "mono-aot-cross.exe"); - var monoAotMode = "full"; - var debugMode = useDebug ? "soft-debug" : "nodebug"; - var aotCompilerArgs = $"--aot={monoAotMode},verbose,stats,print-skipped,{debugMode} -O=all"; - if (useDebug || dotnetAotDebug) - aotCompilerArgs = "--debug " + aotCompilerArgs; - var envVars = new Dictionary(); - envVars["MONO_PATH"] = aotAssembliesPath + ";" + dotnetLibPath; - if (dotnetAotDebug) - { - envVars["MONO_LOG_LEVEL"] = "debug"; - } - - // Run cross-compiler compiler Log.Info(" * " + assemblyPath); - int result = Utilities.Run(aotCompilerPath, $"{aotCompilerArgs} \"{assemblyPath}\"", null, platformToolsRoot, Utilities.RunOptions.AppMustExist | Utilities.RunOptions.ConsoleLogOutput, envVars); - if (result != 0) + var options = new Toolchain.CSharpOptions + { + InputFile = assemblyPath, + AssembliesFolder = aotAssembliesPath, + ClassLibraryPath = dotnetLibPath, + EnableDebugSymbols = useDebug, + EnableToolDebug = dotnetAotDebug, + }; + if (buildToolchain.CompileCSharp(options)) { Log.Error("Failed to run AOT on assembly " + assemblyPath); failed = true; diff --git a/Source/Tools/Flax.Build/Build/DotNet/DotNetSdk.cs b/Source/Tools/Flax.Build/Build/DotNet/DotNetSdk.cs index f52f0b818..b9f1002ce 100644 --- a/Source/Tools/Flax.Build/Build/DotNet/DotNetSdk.cs +++ b/Source/Tools/Flax.Build/Build/DotNet/DotNetSdk.cs @@ -274,6 +274,14 @@ namespace Flax.Build Log.Verbose($" - Host Runtime for {e.Key.Key} {e.Key.Value}"); } + /// + /// Initializes platforms which can register custom host runtime location + /// + private static void InitPlatforms() + { + Platform.GetPlatform(TargetPlatform.Windows, true); + } + /// /// Gets the host runtime identifier for a given platform (eg. linux-arm64). /// @@ -338,6 +346,7 @@ namespace Flax.Build /// public void PrintRuntimes() { + InitPlatforms(); foreach (var e in _hostRuntimes) { // Filter with input commandline @@ -357,6 +366,7 @@ namespace Flax.Build /// public bool GetHostRuntime(TargetPlatform platform, TargetArchitecture arch, out HostRuntime hostRuntime) { + InitPlatforms(); return _hostRuntimes.TryGetValue(new KeyValuePair(platform, arch), out hostRuntime); } diff --git a/Source/Tools/Flax.Build/Build/Toolchain.cs b/Source/Tools/Flax.Build/Build/Toolchain.cs index 8f9703d00..ac8ce6255 100644 --- a/Source/Tools/Flax.Build/Build/Toolchain.cs +++ b/Source/Tools/Flax.Build/Build/Toolchain.cs @@ -133,5 +133,27 @@ namespace Flax.Build /// The build options with linking environment. /// The output file path (result linked file). public abstract void LinkFiles(TaskGraph graph, BuildOptions options, string outputFilePath); + + /// + /// C# compilation options container. + /// + public struct CSharpOptions + { + public string InputFile; + public string AssembliesFolder; + public string ClassLibraryPath; + public bool EnableDebugSymbols; + public bool EnableToolDebug; + } + + /// + /// Compiles the C# assembly with AOT cross-compiler. + /// + /// The options. + /// True if failed, or not supported. + public virtual bool CompileCSharp(CSharpOptions options) + { + return true; + } } } diff --git a/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs b/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs index 0190050fb..2b9fc3941 100644 --- a/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs +++ b/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs @@ -1024,5 +1024,31 @@ namespace Flax.Build.Platforms priNewFile.ProducedFiles.Add(priFile); } } + + /// + public override bool CompileCSharp(CSharpOptions options) + { + var platformToolsRoot = Path.Combine(Globals.EngineRoot, "Source/Platforms", Platform.Target.ToString(), "Binaries/Tools"); + if (!Directory.Exists(platformToolsRoot)) + throw new Exception("Missing platform tools " + platformToolsRoot); + var aotCompilerPath = Path.Combine(platformToolsRoot, "mono-aot-cross.exe"); + + // Setup options + var monoAotMode = "full"; + var debugMode = options.EnableDebugSymbols ? "soft-debug" : "nodebug"; + var aotCompilerArgs = $"--aot={monoAotMode},verbose,stats,print-skipped,{debugMode} -O=all"; + if (options.EnableDebugSymbols || options.EnableToolDebug) + aotCompilerArgs = "--debug " + aotCompilerArgs; + var envVars = new Dictionary(); + envVars["MONO_PATH"] = options.AssembliesFolder + ";" + options.ClassLibraryPath; + if (options.EnableToolDebug) + { + envVars["MONO_LOG_LEVEL"] = "debug"; + } + + // Run cross-compiler compiler + int result = Utilities.Run(aotCompilerPath, $"{aotCompilerArgs} \"{options.InputFile}\"", null, platformToolsRoot, Utilities.RunOptions.AppMustExist | Utilities.RunOptions.ConsoleLogOutput, envVars); + return result != 0; + } } }