Update Switch platform support

This commit is contained in:
Wojtek Figat
2023-04-11 15:53:53 +02:00
parent aa64da9869
commit 68c6a01805
12 changed files with 98 additions and 203 deletions

View File

@@ -415,89 +415,6 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
return false;
}
void UWPPlatformTools::OnConfigureAOT(CookingData& data, AotConfig& config)
{
const auto platformDataPath = data.GetPlatformBinariesRoot();
const bool useInterpreter = true; // TODO: support using Full AOT instead of interpreter
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 UWPPlatformTools::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 UWPPlatformTools::OnPostProcess(CookingData& data)
{
LOG(Error, "UWP (Windows Store) platform has been deprecated and soon will be removed!");

View File

@@ -32,8 +32,6 @@ public:
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;
bool OnPostProcess(CookingData& data) override;
};

View File

@@ -3,7 +3,6 @@
#pragma once
#include "CookingData.h"
#include "Engine/Core/Collections/Dictionary.h"
#include "Editor/Scripting/ScriptsBuilder.h"
#include "Engine/Graphics/PixelFormat.h"
@@ -134,62 +133,6 @@ public:
return false;
}
/// <summary>
/// The C# scripts AOT configuration options.
/// </summary>
struct AotConfig
{
String AotCompilerPath;
String AotCompilerArgs;
String AssemblerPath;
String AssemblerArgs;
String ArchiverPath;
String ArchiverArgs;
String AuxToolPath;
String AuxToolArgs;
String AotCachePath;
Dictionary<String, String> EnvVars;
Array<String> AssembliesSearchDirs;
Array<String> Assemblies;
AotConfig(CookingData& data)
{
Platform::GetEnvironmentVariables(EnvVars);
}
};
/// <summary>
/// Called to configure AOT options.
/// </summary>
/// <param name="data">The cooking data.</param>
/// <param name="config">The configuration.</param>
virtual void OnConfigureAOT(CookingData& data, AotConfig& config)
{
}
/// <summary>
/// Called to execute AOT for the given assembly.
/// </summary>
/// <param name="data">The cooking data.</param>
/// <param name="config">The configuration.</param>
/// <param name="assemblyPath">The input managed library file path.</param>
/// <returns>True if failed, otherwise false.<returns>
virtual bool OnPerformAOT(CookingData& data, AotConfig& config, const String& assemblyPath)
{
return false;
}
/// <summary>
/// Called after AOT execution for the assemblies.
/// </summary>
/// <param name="data">The cooking data.</param>
/// <param name="config">The configuration.</param>
/// <returns>True if failed, otherwise false.<returns>
virtual bool OnPostProcessAOT(CookingData& data, AotConfig& config)
{
return false;
}
/// <summary>
/// Called during staged build post-processing.
/// </summary>

View File

@@ -77,6 +77,13 @@ public class PhysX : DepsModule
}
options.PublicIncludePaths.Add(Path.Combine(Globals.EngineRoot, "Source/ThirdParty/PhysX"));
switch (options.Platform.Target)
{
case TargetPlatform.Switch:
options.PublicIncludePaths.Add(Path.Combine(Globals.EngineRoot, "Source/Platforms", options.Platform.Target.ToString(), "Binaries/Data/PhysX/physx/include"));
options.PublicIncludePaths.Add(Path.Combine(Globals.EngineRoot, "Source/Platforms", options.Platform.Target.ToString(), "Binaries/Data/PhysX/physx/include/foundation"));
break;
}
if (useDynamicLinking)
{

View File

@@ -56,6 +56,7 @@ namespace Flax.Build
public static void RunDotNetAOT()
{
Log.Info("Running .NET AOT in mode " + AOTMode);
Configuration.CustomDefines.Add("DOTNET_AOT_DEBUG");
DotNetAOT.RunAOT();
}
@@ -359,13 +360,22 @@ namespace Flax.Build
useDebug = false;
}
// Get output file path for this assembly (platform can use custom extension)
var options = new Toolchain.CSharpOptions
{
Action = Toolchain.CSharpOptions.ActionTypes.GetOutputFiles,
InputFiles = new List<string>() { assemblyPath },
OutputFiles = new List<string>(),
AssembliesPath = aotAssembliesPath,
ClassLibraryPath = dotnetLibPath,
PlatformsToolsPath = platformsToolsPath,
EnableDebugSymbols = useDebug,
EnableToolDebug = dotnetAotDebug,
};
buildToolchain.CompileCSharp(ref options);
// Skip if output is already generated and is newer than a source assembly
string outputFilePath;
if (aotMode == DotNetAOTModes.MonoAOTDynamic)
outputFilePath = assemblyPath + buildPlatform.SharedLibraryFileExtension;
else
outputFilePath = Path.Combine(Path.GetDirectoryName(assemblyPath), buildPlatform.StaticLibraryFilePrefix + Path.GetFileName(assemblyPath) + buildPlatform.StaticLibraryFileExtension);
if (!File.Exists(outputFilePath) || File.GetLastWriteTime(assemblyPath) > File.GetLastWriteTime(outputFilePath))
if (!File.Exists(options.OutputFiles[0]) || File.GetLastWriteTime(assemblyPath) > File.GetLastWriteTime(options.OutputFiles[0]))
{
if (dotnetAotDebug)
{
@@ -373,21 +383,11 @@ namespace Flax.Build
Log.Info("");
Log.Info("");
}
var options = new Toolchain.CSharpOptions
{
Action = Toolchain.CSharpOptions.ActionTypes.MonoCompile,
InputFile = assemblyPath,
OutputFile = outputFilePath,
AssembliesPath = aotAssembliesPath,
ClassLibraryPath = dotnetLibPath,
PlatformsToolsPath = platformsToolsPath,
EnableDebugSymbols = useDebug,
EnableToolDebug = dotnetAotDebug,
};
if (!Directory.Exists(options.PlatformsToolsPath))
throw new Exception("Missing platform tools " + options.PlatformsToolsPath);
Log.Info(" * " + options.OutputFile);
if (buildToolchain.CompileCSharp(options))
Log.Info(" * " + assemblyPath);
options.Action = Toolchain.CSharpOptions.ActionTypes.MonoCompile;
if (buildToolchain.CompileCSharp(ref options))
{
Log.Error("Failed to run AOT on assembly " + assemblyPath);
failed = true;
@@ -397,19 +397,31 @@ namespace Flax.Build
}
var assemblyFileName = Path.GetFileName(assemblyPath);
// TODO: consider optimizing C# assemblies when doing Mono AOT - maybe we could strip them out of the code and leave just reference/api info for the runtime
if (Configuration.AOTMode == DotNetAOTModes.MonoAOTDynamic)
{
// Skip if deployed file is already valid
var deployedFilePath = Path.Combine(dotnetOutputPath, Path.GetFileName(outputFilePath));
if (!File.Exists(deployedFilePath) || File.GetLastWriteTime(outputFilePath) > File.GetLastWriteTime(deployedFilePath))
{
// Copy to the destination folder
Utilities.FileCopy(assemblyPath, Path.Combine(dotnetOutputPath, assemblyFileName));
Utilities.FileCopy(outputFilePath, deployedFilePath);
if (useDebug && File.Exists(outputFilePath + ".pdb"))
Utilities.FileCopy(outputFilePath + ".pdb", Path.Combine(dotnetOutputPath, Path.GetFileName(outputFilePath + ".pdb")));
validCache = false;
// Copy assembly
var outputFile = Path.Combine(dotnetOutputPath, assemblyFileName);
var deployedFilePath = Path.Combine(dotnetOutputPath, Path.GetFileName(outputFile));
if (!File.Exists(deployedFilePath) || File.GetLastWriteTime(outputFile) > File.GetLastWriteTime(deployedFilePath))
{
Utilities.FileCopy(assemblyPath, outputFile);
}
}
// Copy AOT build products
foreach (var outputFile in options.OutputFiles)
{
// Skip if deployed file is already valid
var deployedFilePath = Path.Combine(dotnetOutputPath, Path.GetFileName(outputFile));
if (!File.Exists(deployedFilePath) || File.GetLastWriteTime(outputFile) > File.GetLastWriteTime(deployedFilePath))
{
// Copy to the destination folder
Utilities.FileCopy(outputFile, deployedFilePath);
if (useDebug && File.Exists(outputFile + ".pdb"))
Utilities.FileCopy(outputFile + ".pdb", Path.Combine(dotnetOutputPath, Path.GetFileName(outputFile + ".pdb")));
validCache = false;
}
}
}
else
@@ -439,15 +451,15 @@ namespace Flax.Build
{
Action = Toolchain.CSharpOptions.ActionTypes.MonoLink,
InputFiles = assembliesPaths,
OutputFile = outputAotLib,
OutputFiles = new List<string>() { outputAotLib },
AssembliesPath = aotAssembliesPath,
ClassLibraryPath = dotnetLibPath,
PlatformsToolsPath = platformsToolsPath,
EnableDebugSymbols = configuration != TargetConfiguration.Release,
EnableToolDebug = dotnetAotDebug,
};
Log.Info(" * " + options.OutputFile);
if (buildToolchain.CompileCSharp(options))
Log.Info(" * " + outputAotLib);
if (buildToolchain.CompileCSharp(ref options))
{
throw new Exception("Mono AOT failed to link static libraries into a shared module");
}

View File

@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using System.IO;
using Flax.Build.Graph;
using Flax.Build.NativeCpp;
@@ -143,12 +144,12 @@ namespace Flax.Build
{
MonoCompile,
MonoLink,
GetOutputFiles,
};
public ActionTypes Action;
public string InputFile;
public List<string> InputFiles;
public string OutputFile;
public List<string> OutputFiles;
public string AssembliesPath;
public string ClassLibraryPath;
public string PlatformsToolsPath;
@@ -161,8 +162,20 @@ namespace Flax.Build
/// </summary>
/// <param name="options">The options.</param>
/// <returns>True if failed, or not supported.</returns>
public virtual bool CompileCSharp(CSharpOptions options)
public virtual bool CompileCSharp(ref CSharpOptions options)
{
switch (options.Action)
{
case CSharpOptions.ActionTypes.GetOutputFiles:
foreach (var inputFile in options.InputFiles)
{
if (Configuration.AOTMode == DotNetAOTModes.MonoAOTDynamic)
options.OutputFiles.Add(inputFile + Platform.SharedLibraryFileExtension);
else
options.OutputFiles.Add(Path.Combine(Path.GetDirectoryName(inputFile), Platform.StaticLibraryFilePrefix + Path.GetFileName(inputFile) + Platform.StaticLibraryFileExtension));
}
return false;
}
return true;
}
}

View File

@@ -407,7 +407,7 @@ namespace Flax.Deps.Dependencies
}
case TargetPlatform.Switch:
{
Utilities.DirectoryCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "PhysX"), root, true, true);
Utilities.DirectoryCopy(Path.Combine(GetBinariesFolder(options, platform), "Data", "PhysX"), root, true, true);
Build(options, "switch64", platform, TargetArchitecture.ARM64);
break;
}

View File

@@ -234,7 +234,7 @@ namespace Flax.Deps.Dependencies
// PS4 outputs mono into artifacts\obj\mono\PS4.x64.Release\out
// PS4 outputs native libs into artifacts\bin\native\net7.0-PS4-Release-x64\lib
// PS4 outputs System.Private.CoreLib lib into artifacts\bin\mono\PS4.x64.Release
// PS4 outputs C# libs into artifacts\bin\mono\PS4.x64.Release\cross\ps4-x64
// PS4 outputs C# libs into artifacts\bin\runtime\net7.0-PS4.Release.x64
// PS4 outputs AOT compiler into artifacts\bin\mono\PS4.x64.Release\cross\ps4-x64
Utilities.DirectoryCopy(Path.Combine(unpackTemp, "runtimes", hostRuntimeName, "native"), Path.Combine(dstDotnet, "native"), true, true);
Utilities.FileDelete(Path.Combine(dstDotnet, "native", privateCorelib));

View File

@@ -204,7 +204,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Switch:
{
// Get the build data files
Utilities.DirectoryCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "ogg"), root, true, true);
Utilities.DirectoryCopy(Path.Combine(GetBinariesFolder(options, platform), "Data", "ogg"), root, true, true);
// Build for Switch
SetupDirectory(buildDir, true);

View File

@@ -348,14 +348,14 @@ namespace Flax.Deps.Dependencies
GitCheckout(root, "master", "98eddc72d36e3421519d54b101c09b57e4d4d10d");
CloneGitRepo(oggRoot, "https://github.com/xiph/ogg.git");
GitCheckout(oggRoot, "master", "4380566a44b8d5e85ad511c9c17eb04197863ec5");
Utilities.DirectoryCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "ogg"), oggRoot, true, true);
Utilities.DirectoryCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "vorbis"), buildDir, true, true);
Utilities.DirectoryCopy(Path.Combine(GetBinariesFolder(options, platform), "ogg"), oggRoot, true, true);
Utilities.DirectoryCopy(Path.Combine(GetBinariesFolder(options, platform), "vorbis"), buildDir, true, true);
// Build for Switch
SetupDirectory(oggBuildDir, true);
RunCmake(oggBuildDir, platform, TargetArchitecture.ARM64, ".. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=\"../install\"");
Utilities.Run("cmake", "--build . --target install", null, oggBuildDir, Utilities.RunOptions.None);
Utilities.FileCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "ogg", "include", "ogg", "config_types.h"), Path.Combine(oggRoot, "install", "include", "ogg", "config_types.h"));
Utilities.FileCopy(Path.Combine(GetBinariesFolder(options, platform), "ogg", "include", "ogg", "config_types.h"), Path.Combine(oggRoot, "install", "include", "ogg", "config_types.h"));
SetupDirectory(buildDir, true);
RunCmake(buildDir, platform, TargetArchitecture.ARM64, string.Format(".. -DCMAKE_BUILD_TYPE=Release -DOGG_INCLUDE_DIR=\"{0}/install/include\" -DOGG_LIBRARY=\"{0}/install/lib\"", oggRoot));
Utilities.Run("cmake", "--build .", null, buildDir, Utilities.RunOptions.None);

View File

@@ -284,7 +284,7 @@ namespace Flax.Deps
}
case TargetPlatform.Switch:
{
cmdLine = string.Format("-DCMAKE_TOOLCHAIN_FILE=\"{1}\\Source\\Platforms\\Switch\\Data\\Switch.cmake\" -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=\"{0}..\\..\\VC\\bin\\nmake.exe\"", Environment.GetEnvironmentVariable("VS140COMNTOOLS"), Globals.EngineRoot);
cmdLine = string.Format("-DCMAKE_TOOLCHAIN_FILE=\"{1}\\Source\\Platforms\\Switch\\Binaries\\Data\\Switch.cmake\" -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=\"{0}..\\..\\VC\\bin\\nmake.exe\"", Environment.GetEnvironmentVariable("VS140COMNTOOLS"), Globals.EngineRoot);
break;
}
case TargetPlatform.Android:

View File

@@ -1026,28 +1026,33 @@ namespace Flax.Build.Platforms
}
/// <inheritdoc />
public override bool CompileCSharp(CSharpOptions options)
public override bool CompileCSharp(ref CSharpOptions options)
{
if (options.Action != CSharpOptions.ActionTypes.MonoCompile)
return true;
var aotCompilerPath = Path.Combine(options.PlatformsToolsPath, "mono-aot-cross.exe");
// Setup options
var monoAotMode = "full";
var monoDebugMode = options.EnableDebugSymbols ? "soft-debug" : "nodebug";
var aotCompilerArgs = $"--aot={monoAotMode},verbose,stats,print-skipped,{monoDebugMode} -O=all";
if (options.EnableDebugSymbols || options.EnableToolDebug)
aotCompilerArgs = "--debug " + aotCompilerArgs;
var envVars = new Dictionary<string, string>();
envVars["MONO_PATH"] = options.AssembliesPath + ";" + options.ClassLibraryPath;
if (options.EnableToolDebug)
switch (options.Action)
{
envVars["MONO_LOG_LEVEL"] = "debug";
}
case CSharpOptions.ActionTypes.MonoCompile:
{
var aotCompilerPath = Path.Combine(options.PlatformsToolsPath, "mono-aot-cross.exe");
// Run cross-compiler compiler
int result = Utilities.Run(aotCompilerPath, $"{aotCompilerArgs} \"{options.InputFile}\"", null, options.PlatformsToolsPath, Utilities.RunOptions.AppMustExist | Utilities.RunOptions.ConsoleLogOutput, envVars);
return result != 0;
// Setup options
var monoAotMode = "full";
var monoDebugMode = options.EnableDebugSymbols ? "soft-debug" : "nodebug";
var aotCompilerArgs = $"--aot={monoAotMode},verbose,stats,print-skipped,{monoDebugMode} -O=all";
if (options.EnableDebugSymbols || options.EnableToolDebug)
aotCompilerArgs = "--debug " + aotCompilerArgs;
var envVars = new Dictionary<string, string>();
envVars["MONO_PATH"] = options.AssembliesPath + ";" + options.ClassLibraryPath;
if (options.EnableToolDebug)
{
envVars["MONO_LOG_LEVEL"] = "debug";
}
// Run cross-compiler compiler
int result = Utilities.Run(aotCompilerPath, $"{aotCompilerArgs} \"{options.InputFiles[0]}\"", null, options.PlatformsToolsPath, Utilities.RunOptions.AppMustExist | Utilities.RunOptions.ConsoleLogOutput, envVars);
return result != 0;
}
}
return base.CompileCSharp(ref options);
}
}
}