Add SkipUnusedDotnetLibsPackaging to build settings for optional whole C# stdlib packaging
This commit is contained in:
@@ -14,13 +14,14 @@ void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
|
|||||||
const DotNetAOTModes aotMode = data.Tools->UseAOT();
|
const DotNetAOTModes aotMode = data.Tools->UseAOT();
|
||||||
if (aotMode == DotNetAOTModes::None)
|
if (aotMode == DotNetAOTModes::None)
|
||||||
return;
|
return;
|
||||||
|
const auto& buildSettings = *BuildSettings::Get();
|
||||||
|
|
||||||
// Redirect C# assemblies to intermediate cooking directory (processed by ILC)
|
// Redirect C# assemblies to intermediate cooking directory (processed by ILC)
|
||||||
data.ManagedCodeOutputPath = data.CacheDirectory / TEXT("AOTAssemblies");
|
data.ManagedCodeOutputPath = data.CacheDirectory / TEXT("AOTAssemblies");
|
||||||
|
|
||||||
// Reset any AOT cache from previous run if the AOT mode has changed (eg. Mono AOT -> ILC on Desktop)
|
// Reset any AOT cache from previous run if the AOT mode has changed (eg. Mono AOT -> ILC on Desktop)
|
||||||
const String aotModeCacheFilePath = data.ManagedCodeOutputPath / TEXT("AOTMode.txt");
|
const String aotModeCacheFilePath = data.ManagedCodeOutputPath / TEXT("AOTMode.txt");
|
||||||
String aotModeCacheValue = String::Format(TEXT("{};{}"), (int32)aotMode, (int32)data.Configuration);
|
String aotModeCacheValue = String::Format(TEXT("{};{};{}"), (int32)aotMode, (int32)data.Configuration, (int32)buildSettings.SkipUnusedDotnetLibsPackaging);
|
||||||
for (const String& define : data.CustomDefines)
|
for (const String& define : data.CustomDefines)
|
||||||
aotModeCacheValue += define;
|
aotModeCacheValue += define;
|
||||||
if (FileSystem::DirectoryExists(data.ManagedCodeOutputPath))
|
if (FileSystem::DirectoryExists(data.ManagedCodeOutputPath))
|
||||||
@@ -60,9 +61,11 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
|
|||||||
const Char *platform, *architecture, *configuration = ::ToString(data.Configuration);
|
const Char *platform, *architecture, *configuration = ::ToString(data.Configuration);
|
||||||
data.GetBuildPlatformName(platform, architecture);
|
data.GetBuildPlatformName(platform, architecture);
|
||||||
const String logFile = data.CacheDirectory / TEXT("AotLog.txt");
|
const String logFile = data.CacheDirectory / TEXT("AotLog.txt");
|
||||||
auto args = String::Format(
|
String args = String::Format(
|
||||||
TEXT("-log -logfile=\"{}\" -runDotNetAOT -mutex -platform={} -arch={} -configuration={} -aotMode={} -binaries=\"{}\" -intermediate=\"{}\""),
|
TEXT("-log -logfile=\"{}\" -runDotNetAOT -mutex -platform={} -arch={} -configuration={} -aotMode={} -binaries=\"{}\" -intermediate=\"{}\""),
|
||||||
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath);
|
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath);
|
||||||
|
if (!buildSettings.SkipUnusedDotnetLibsPackaging)
|
||||||
|
args += TEXT(" -skipUnusedDotnetLibs=false"); // Run AOT on whole class library (not just used libs)
|
||||||
for (const String& define : data.CustomDefines)
|
for (const String& define : data.CustomDefines)
|
||||||
{
|
{
|
||||||
args += TEXT(" -D");
|
args += TEXT(" -D");
|
||||||
|
|||||||
@@ -77,11 +77,17 @@ public:
|
|||||||
bool ShadersGenerateDebugData = false;
|
bool ShadersGenerateDebugData = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If checked, .NET 7 Runtime won't be packaged with a game and will be required by user to be installed on system upon running game build. Available only on supported platforms such as Windows, Linux and macOS.
|
/// If checked, .NET Runtime won't be packaged with a game and will be required by user to be installed on system upon running game build. Available only on supported platforms such as Windows, Linux and macOS.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="EditorOrder(3000), EditorDisplay(\"Scripting\", \"Skip .NET Runtime Packaging\")")
|
API_FIELD(Attributes="EditorOrder(3000), EditorDisplay(\"Scripting\", \"Skip .NET Runtime Packaging\")")
|
||||||
bool SkipDotnetPackaging = false;
|
bool SkipDotnetPackaging = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If checked, .NET Runtime packaging will skip unused libraries from packaging resulting in smaller game builds.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(3010), EditorDisplay(\"Scripting\", \"Skip Unused .NET Runtime Libs Packaging\")")
|
||||||
|
bool SkipUnusedDotnetLibsPackaging = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
|
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
|
||||||
@@ -101,5 +107,6 @@ public:
|
|||||||
DESERIALIZE(ShadersNoOptimize);
|
DESERIALIZE(ShadersNoOptimize);
|
||||||
DESERIALIZE(ShadersGenerateDebugData);
|
DESERIALIZE(ShadersGenerateDebugData);
|
||||||
DESERIALIZE(SkipDotnetPackaging);
|
DESERIALIZE(SkipDotnetPackaging);
|
||||||
|
DESERIALIZE(SkipUnusedDotnetLibsPackaging);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ namespace Flax.Build
|
|||||||
[CommandLine("aotMode", "")]
|
[CommandLine("aotMode", "")]
|
||||||
public static DotNetAOTModes AOTMode;
|
public static DotNetAOTModes AOTMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See SkipUnusedDotnetLibsPackaging in BuildSettings.
|
||||||
|
/// </summary>
|
||||||
|
[CommandLine("skipUnusedDotnetLibs", "")]
|
||||||
|
public static bool SkipUnusedDotnetLibsPackaging = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes AOT process as a part of the game cooking (called by PrecompileAssembliesStep in Editor).
|
/// Executes AOT process as a part of the game cooking (called by PrecompileAssembliesStep in Editor).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -85,7 +91,7 @@ namespace Flax.Build
|
|||||||
|
|
||||||
// Find input files
|
// Find input files
|
||||||
var inputFiles = Directory.GetFiles(aotAssembliesPath, "*.dll", SearchOption.TopDirectoryOnly).ToList();
|
var inputFiles = Directory.GetFiles(aotAssembliesPath, "*.dll", SearchOption.TopDirectoryOnly).ToList();
|
||||||
inputFiles.RemoveAll(x => x.EndsWith(".dll.dll") || Path.GetFileName(x) == "BuilderRulesCache.dll");
|
inputFiles.RemoveAll(FilterAssembly);
|
||||||
for (int i = 0; i < inputFiles.Count; i++)
|
for (int i = 0; i < inputFiles.Count; i++)
|
||||||
inputFiles[i] = Utilities.NormalizePath(inputFiles[i]);
|
inputFiles[i] = Utilities.NormalizePath(inputFiles[i]);
|
||||||
inputFiles.Sort();
|
inputFiles.Sort();
|
||||||
@@ -239,6 +245,9 @@ namespace Flax.Build
|
|||||||
|
|
||||||
// Build list of assemblies to process (use game assemblies as root to walk over used references from stdlib)
|
// Build list of assemblies to process (use game assemblies as root to walk over used references from stdlib)
|
||||||
var assembliesPaths = new List<string>();
|
var assembliesPaths = new List<string>();
|
||||||
|
if (Configuration.SkipUnusedDotnetLibsPackaging)
|
||||||
|
{
|
||||||
|
// Use game assemblies as root to walk over used references from stdlib
|
||||||
using (var assemblyResolver = new MonoCecil.BasicAssemblyResolver())
|
using (var assemblyResolver = new MonoCecil.BasicAssemblyResolver())
|
||||||
{
|
{
|
||||||
assemblyResolver.SearchDirectories.Add(aotAssembliesPath);
|
assemblyResolver.SearchDirectories.Add(aotAssembliesPath);
|
||||||
@@ -258,8 +267,21 @@ namespace Flax.Build
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use all libs
|
||||||
|
var stdLibFiles = Directory.GetFiles(dotnetLibPath, "*.dll", SearchOption.TopDirectoryOnly).ToList();
|
||||||
|
stdLibFiles.RemoveAll(FilterAssembly);
|
||||||
|
for (int i = 0; i < stdLibFiles.Count; i++)
|
||||||
|
stdLibFiles[i] = Utilities.NormalizePath(stdLibFiles[i]);
|
||||||
|
stdLibFiles.Sort();
|
||||||
|
assembliesPaths.AddRange(stdLibFiles);
|
||||||
|
assembliesPaths.AddRange(inputFiles);
|
||||||
|
}
|
||||||
|
|
||||||
// Run compilation
|
// Run compilation
|
||||||
|
bool failed = false;
|
||||||
var compileAssembly = (string assemblyPath) =>
|
var compileAssembly = (string assemblyPath) =>
|
||||||
{
|
{
|
||||||
// Determinate whether use debug information for that assembly
|
// Determinate whether use debug information for that assembly
|
||||||
@@ -297,7 +319,13 @@ namespace Flax.Build
|
|||||||
|
|
||||||
// Run cross-compiler compiler
|
// Run cross-compiler compiler
|
||||||
Log.Info(" * " + assemblyPath);
|
Log.Info(" * " + assemblyPath);
|
||||||
Utilities.Run(aotCompilerPath, $"{aotCompilerArgs} \"{assemblyPath}\"", null, platformToolsRoot, Utilities.RunOptions.AppMustExist | Utilities.RunOptions.ThrowExceptionOnError | Utilities.RunOptions.ConsoleLogOutput, envVars);
|
int result = Utilities.Run(aotCompilerPath, $"{aotCompilerArgs} \"{assemblyPath}\"", null, platformToolsRoot, Utilities.RunOptions.AppMustExist | Utilities.RunOptions.ConsoleLogOutput, envVars);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
Log.Error("Failed to run AOT on assembly " + assemblyPath);
|
||||||
|
failed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if deployed file is already valid
|
// Skip if deployed file is already valid
|
||||||
@@ -323,6 +351,8 @@ namespace Flax.Build
|
|||||||
foreach (var assemblyPath in assembliesPaths)
|
foreach (var assemblyPath in assembliesPaths)
|
||||||
compileAssembly(assemblyPath);
|
compileAssembly(assemblyPath);
|
||||||
}
|
}
|
||||||
|
if (failed)
|
||||||
|
throw new Exception($"Failed to run AOT. See log ({Configuration.LogFile}).");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -334,6 +364,28 @@ namespace Flax.Build
|
|||||||
Utilities.FileCopy(Path.Combine(aotAssembliesPath, "THIRD-PARTY-NOTICES.TXT"), Path.Combine(dotnetOutputPath, "THIRD-PARTY-NOTICES.TXT"));
|
Utilities.FileCopy(Path.Combine(aotAssembliesPath, "THIRD-PARTY-NOTICES.TXT"), Path.Combine(dotnetOutputPath, "THIRD-PARTY-NOTICES.TXT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool FilterAssembly(string x)
|
||||||
|
{
|
||||||
|
// Skip AOT output products
|
||||||
|
if (x.EndsWith(".dll.dll"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Skip Flax.Build rules assembly
|
||||||
|
if (Path.GetFileName(x) == "BuilderRulesCache.dll")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Skip non-C# DLLs
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(x, new ReaderParameters { ReadSymbols = false, InMemory = true, ReadingMode = ReadingMode.Deferred }))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal static void BuildAssembliesList(string assemblyPath, List<string> outputList, IAssemblyResolver assemblyResolver, string callerPath, HashSet<string> warnings)
|
internal static void BuildAssembliesList(string assemblyPath, List<string> outputList, IAssemblyResolver assemblyResolver, string callerPath, HashSet<string> warnings)
|
||||||
{
|
{
|
||||||
// Skip if already processed
|
// Skip if already processed
|
||||||
|
|||||||
Reference in New Issue
Block a user