Add automatic building of nethost for consoles
This commit is contained in:
@@ -9,8 +9,6 @@ using Flax.Build.Platforms;
|
||||
using Flax.Deploy;
|
||||
using System.IO.Compression;
|
||||
|
||||
#pragma warning disable 0219
|
||||
|
||||
namespace Flax.Deps.Dependencies
|
||||
{
|
||||
/// <summary>
|
||||
@@ -30,6 +28,7 @@ namespace Flax.Deps.Dependencies
|
||||
return new[]
|
||||
{
|
||||
TargetPlatform.PS4,
|
||||
TargetPlatform.PS5,
|
||||
TargetPlatform.Switch,
|
||||
};
|
||||
case TargetPlatform.Linux:
|
||||
@@ -46,6 +45,7 @@ namespace Flax.Deps.Dependencies
|
||||
public override bool BuildByDefault => false;
|
||||
|
||||
private string root;
|
||||
private bool cleanArtifacts;
|
||||
|
||||
private void Build(BuildOptions options, TargetPlatform targetPlatform, TargetArchitecture architecture)
|
||||
{
|
||||
@@ -55,13 +55,14 @@ namespace Flax.Deps.Dependencies
|
||||
|
||||
// Clean output directory
|
||||
var artifacts = Path.Combine(root, "artifacts");
|
||||
SetupDirectory(artifacts, true);
|
||||
SetupDirectory(artifacts, cleanArtifacts);
|
||||
cleanArtifacts = true;
|
||||
|
||||
// Peek options
|
||||
string os, arch, runtimeFlavor, subset, hostRuntimeName = DotNetSdk.GetHostRuntimeIdentifier(targetPlatform, architecture), buildArgsBase = string.Empty;
|
||||
bool setupVersion = false;
|
||||
string[] hostRuntimeFiles = Array.Empty<string>();
|
||||
string os, arch, runtimeFlavor, hostRuntimeName = DotNetSdk.GetHostRuntimeIdentifier(targetPlatform, architecture), buildArgs = string.Empty, buildMonoAotCrossArgs = string.Empty;
|
||||
bool setupVersion = false, buildMonoAotCross = false;
|
||||
var envVars = new Dictionary<string, string>();
|
||||
envVars.Add("VisualStudioVersion", null); // Unset this so 'init-vs-env.cmd' will properly init VS Environment
|
||||
switch (architecture)
|
||||
{
|
||||
case TargetArchitecture.x86:
|
||||
@@ -83,36 +84,39 @@ namespace Flax.Deps.Dependencies
|
||||
case TargetPlatform.Windows:
|
||||
os = "windows";
|
||||
runtimeFlavor = "CoreCLR";
|
||||
subset = "clr";
|
||||
break;
|
||||
case TargetPlatform.Linux:
|
||||
os = "Linux";
|
||||
os = "linux";
|
||||
runtimeFlavor = "CoreCLR";
|
||||
subset = "clr";
|
||||
break;
|
||||
case TargetPlatform.Mac:
|
||||
os = "OSX";
|
||||
os = "osx";
|
||||
runtimeFlavor = "CoreCLR";
|
||||
subset = "clr";
|
||||
break;
|
||||
case TargetPlatform.Android:
|
||||
os = "Android";
|
||||
os = "android";
|
||||
runtimeFlavor = "Mono";
|
||||
subset = "mono+libs";
|
||||
break;
|
||||
case TargetPlatform.PS4:
|
||||
os = "PS4";
|
||||
case TargetPlatform.PS5:
|
||||
case TargetPlatform.Switch:
|
||||
runtimeFlavor = "Mono";
|
||||
subset = "mono+libs";
|
||||
setupVersion = true;
|
||||
buildArgsBase = " /p:RuntimeOS=ps4 -cmakeargs \"-DCLR_CROSS_COMPONENTS_BUILD=1\"";
|
||||
hostRuntimeFiles = new[]
|
||||
buildMonoAotCross = true;
|
||||
switch (targetPlatform)
|
||||
{
|
||||
"coreclr_delegates.h",
|
||||
"hostfxr.h",
|
||||
"nethost.h",
|
||||
"libnethost.a",
|
||||
};
|
||||
case TargetPlatform.PS4:
|
||||
os = "ps4";
|
||||
break;
|
||||
case TargetPlatform.PS5:
|
||||
os = "ps5";
|
||||
break;
|
||||
case TargetPlatform.Switch:
|
||||
os = "switch";
|
||||
break;
|
||||
default: throw new InvalidPlatformException(targetPlatform);
|
||||
}
|
||||
buildArgs = $" /p:RuntimeOS={os} -subset mono+libs -cmakeargs \"-DDISABLE_JIT=1-DENABLE_PERFTRACING=0-DDISABLE_REFLECTION_EMIT=1-DDISABLE_EVENTPIPE=1-DDISABLE_COM=1-DDISABLE_PROFILER=1-DDISABLE_COMPONENTS=1\" /p:FeaturePerfTracing=false /p:FeatureManagedEtw=false /p:FeatureManagedEtwChannels=false /p:FeatureEtw=false /p:ApiCompatValidateAssemblies=false";
|
||||
break;
|
||||
default: throw new InvalidPlatformException(targetPlatform);
|
||||
}
|
||||
@@ -175,74 +179,85 @@ namespace Flax.Deps.Dependencies
|
||||
}
|
||||
|
||||
// Build
|
||||
buildArgsBase = $"-os {os} -a {arch} -f {framework} -c {configuration} -lc {configuration} -rc {configuration} -rf {runtimeFlavor}{buildArgsBase}";
|
||||
//foreach (var buildStep in new[] { subset, "host.pkg", "packs.product" })
|
||||
/*var buildStep = "host.pkg";
|
||||
if (runtimeFlavor == "CoreCLR")
|
||||
buildArgs = $"-os {os} -a {arch} -f {framework} -c {configuration} -lc {configuration} -rc {configuration} -rf {runtimeFlavor}{buildArgs}";
|
||||
else if (runtimeFlavor == "Mono")
|
||||
buildArgs = $"-os {os} -a {arch} -c {configuration} -rf {runtimeFlavor}{buildArgs}";
|
||||
Utilities.Run(Path.Combine(root, buildScript), buildArgs, null, root, Utilities.RunOptions.DefaultTool, envVars);
|
||||
if (buildMonoAotCross)
|
||||
{
|
||||
var buildArgs = $"{buildArgsBase} -s {buildStep}";
|
||||
if (BuildPlatform == TargetPlatform.Windows)
|
||||
{
|
||||
// For some reason running from Visual Studio fails the build so use command shell
|
||||
//buildArgs = $"/C {buildScript} {buildArgs}";
|
||||
//buildApp = "cmd.exe";
|
||||
// TODO: maybe write command line into bat file and run it here?
|
||||
WinAPI.SetClipboard($"{buildScript} {buildArgs}");
|
||||
WinAPI.MessageBox.Show($"Open console command in folder '{root}' and run command from clipboard. Then close this dialog.", "Run command manually", WinAPI.MessageBox.Buttons.Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Utilities.Run(Path.Combine(root, buildScript), buildArgs, null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
|
||||
}
|
||||
}*/
|
||||
Utilities.Run(Path.Combine(root, buildScript), buildArgsBase, null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
|
||||
buildMonoAotCrossArgs = $"-c {configuration} -rf {runtimeFlavor} -subset mono /p:BuildMonoAotCrossCompiler=true /p:BuildMonoAOTCrossCompilerOnly=true /p:TargetOS={os} /p:HostOS=windows -cmakeargs \"-DCMAKE_CROSSCOMPILING=True\"{buildMonoAotCrossArgs}";
|
||||
Utilities.Run(Path.Combine(root, buildScript), buildMonoAotCrossArgs, null, root, Utilities.RunOptions.DefaultTool, envVars);
|
||||
}
|
||||
|
||||
// Deploy build products
|
||||
var privateCoreLib = "System.Private.CoreLib.dll";
|
||||
var dstBinaries = GetThirdPartyFolder(options, targetPlatform, architecture);
|
||||
var srcHostRuntime = Path.Combine(artifacts, "bin", $"{hostRuntimeName}.{configuration}", "corehost");
|
||||
foreach (var file in hostRuntimeFiles)
|
||||
{
|
||||
Utilities.FileCopy(Path.Combine(srcHostRuntime, file), Path.Combine(dstBinaries, file));
|
||||
}
|
||||
var dstDotnet = Path.Combine(GetBinariesFolder(options, targetPlatform), "Dotnet");
|
||||
var dstClassLibrary = Path.Combine(dstDotnet, "shared", "Microsoft.NETCore.App", version);
|
||||
SetupDirectory(dstClassLibrary, true);
|
||||
foreach (var file in new[]
|
||||
{
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
})
|
||||
{
|
||||
var dstPlatform = Path.Combine(options.PlatformsFolder, targetPlatform.ToString());
|
||||
var dstDotnet = Path.Combine(dstPlatform, "Dotnet");
|
||||
foreach (var file in new[] { "LICENSE.TXT", "THIRD-PARTY-NOTICES.TXT" })
|
||||
Utilities.FileCopy(Path.Combine(root, file), Path.Combine(dstDotnet, file));
|
||||
}
|
||||
var srcDotnetLibsPkg = Path.Combine(artifacts, "packages", "Release", "Shipping", $"Microsoft.NETCore.App.Runtime.Mono.{hostRuntimeName}.{version}.nupkg");
|
||||
if (!File.Exists(srcDotnetLibsPkg))
|
||||
throw new Exception($"Missing .NET Core App class library package at '{srcDotnetLibsPkg}'");
|
||||
var unpackTemp = Path.Combine(Path.GetDirectoryName(srcDotnetLibsPkg), "UnpackTemp");
|
||||
SetupDirectory(unpackTemp, true);
|
||||
using (var zip = ZipFile.Open(srcDotnetLibsPkg, ZipArchiveMode.Read))
|
||||
if (runtimeFlavor == "CoreCLR")
|
||||
{
|
||||
zip.ExtractToDirectory(unpackTemp);
|
||||
}
|
||||
var privateCorelib = "System.Private.CoreLib.dll";
|
||||
Utilities.FileCopy(Path.Combine(unpackTemp, "runtimes", hostRuntimeName, "native", privateCorelib), Path.Combine(dstClassLibrary, privateCorelib));
|
||||
Utilities.DirectoryCopy(Path.Combine(unpackTemp, "runtimes", hostRuntimeName, "lib", "net8.0"), dstClassLibrary, false, true);
|
||||
// TODO: host/fxr/<version>/hostfxr.dll
|
||||
// TODO: shared/Microsoft.NETCore.App/<version>/hostpolicy.dl
|
||||
// TODO: shared/Microsoft.NETCore.App/<version>/System.IO.Compression.Native.dll
|
||||
if (runtimeFlavor == "Mono")
|
||||
{
|
||||
// TODO: implement automatic deployment based on the setup:
|
||||
// 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\runtime\net7.0-PS4.Release.x64
|
||||
// PS4 outputs AOT compiler into artifacts\bin\mono\PS4.x64.Release\cross\ps4-x64
|
||||
var srcHostRuntime = Path.Combine(artifacts, "bin", $"{hostRuntimeName}.{configuration}", "corehost");
|
||||
var dstClassLibrary = Path.Combine(dstDotnet, "shared", "Microsoft.NETCore.App", version);
|
||||
SetupDirectory(dstClassLibrary, true);
|
||||
var srcDotnetLibsPkg = Path.Combine(artifacts, "packages", "Release", "Shipping", $"Microsoft.NETCore.App.Runtime.Mono.{hostRuntimeName}.{version}.nupkg");
|
||||
if (!File.Exists(srcDotnetLibsPkg))
|
||||
throw new Exception($"Missing .NET Core App class library package at '{srcDotnetLibsPkg}'");
|
||||
var unpackTemp = Path.Combine(Path.GetDirectoryName(srcDotnetLibsPkg), "UnpackTemp");
|
||||
SetupDirectory(unpackTemp, true);
|
||||
using (var zip = ZipFile.Open(srcDotnetLibsPkg, ZipArchiveMode.Read))
|
||||
zip.ExtractToDirectory(unpackTemp);
|
||||
Utilities.FileCopy(Path.Combine(unpackTemp, "runtimes", hostRuntimeName, "native", privateCoreLib), Path.Combine(dstClassLibrary, privateCoreLib));
|
||||
Utilities.DirectoryCopy(Path.Combine(unpackTemp, "runtimes", hostRuntimeName, "lib", framework), dstClassLibrary, false, true);
|
||||
// TODO: host/fxr/<version>/hostfxr.dll
|
||||
// TODO: shared/Microsoft.NETCore.App/<version>/hostpolicy.dl
|
||||
// TODO: shared/Microsoft.NETCore.App/<version>/System.IO.Compression.Native.dll
|
||||
Utilities.DirectoryCopy(Path.Combine(unpackTemp, "runtimes", hostRuntimeName, "native"), Path.Combine(dstDotnet, "native"), true, true);
|
||||
Utilities.FileDelete(Path.Combine(dstDotnet, "native", privateCorelib));
|
||||
Utilities.FileDelete(Path.Combine(dstDotnet, "native", privateCoreLib));
|
||||
Utilities.DirectoriesDelete(unpackTemp);
|
||||
}
|
||||
else if (runtimeFlavor == "Mono")
|
||||
{
|
||||
// Native libs
|
||||
var src1 = Path.Combine(artifacts, "obj", "mono", $"{os}.{arch}.{configuration}", "out");
|
||||
if (!Directory.Exists(src1))
|
||||
throw new DirectoryNotFoundException(src1);
|
||||
var src2 = Path.Combine(artifacts, "bin", "native", $"{framework}-{os}-{configuration}-{arch}");
|
||||
if (!Directory.Exists(src1))
|
||||
throw new DirectoryNotFoundException(src2);
|
||||
foreach (var file in new[]
|
||||
{
|
||||
"libmonosgen-2.0.a",
|
||||
"libmono-profiler-aot.a",
|
||||
})
|
||||
Utilities.FileCopy(Path.Combine(src1, "lib", file), Path.Combine(dstBinaries, file));
|
||||
foreach (var file in new[]
|
||||
{
|
||||
"libSystem.Globalization.Native.a",
|
||||
"libSystem.IO.Compression.Native.a",
|
||||
"libSystem.IO.Ports.Native.a",
|
||||
"libSystem.Native.a",
|
||||
})
|
||||
Utilities.FileCopy(Path.Combine(src2, "lib", file), Path.Combine(dstBinaries, file));
|
||||
|
||||
// Include headers
|
||||
Utilities.DirectoryDelete(Path.Combine(dstBinaries, "include"));
|
||||
Utilities.DirectoryCopy(Path.Combine(src1, "include"), Path.Combine(dstBinaries, "include"), true, true);
|
||||
|
||||
if (buildMonoAotCross)
|
||||
{
|
||||
// AOT compiler
|
||||
Utilities.FileCopy(Path.Combine(artifacts, "bin", "mono", $"{os}.x64.{configuration}", "cross", $"{os}-x64", "mono-aot-cross.exe"), Path.Combine(dstPlatform, "Binaries", "Tools", "mono-aot-cross.exe"));
|
||||
}
|
||||
|
||||
// Class library
|
||||
var dstDotnetLib = Path.Combine(dstPlatform, "Dotnet", "lib", framework);
|
||||
SetupDirectory(dstDotnetLib, true);
|
||||
Utilities.FileCopy(Path.Combine(artifacts, "bin", "mono", $"{os}.{arch}.{configuration}", privateCoreLib), Path.Combine(dstDotnetLib, privateCoreLib));
|
||||
Utilities.DirectoryCopy(Path.Combine(artifacts, "bin", "runtime", $"{framework}-{os}-{configuration}-{arch}"), dstDotnetLib, false, true, "*.dll");
|
||||
}
|
||||
else
|
||||
throw new InvalidPlatformException(targetPlatform);
|
||||
Utilities.DirectoriesDelete(unpackTemp);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -255,9 +270,12 @@ namespace Flax.Deps.Dependencies
|
||||
Utilities.Run("cmake", "--version", null, null, Utilities.RunOptions.ThrowExceptionOnError);
|
||||
|
||||
// Get the source
|
||||
CloneGitRepo(root, "https://github.com/FlaxEngine/dotnet-runtime.git", null, null, true);
|
||||
GitCheckout(root, "flax-master");
|
||||
SetupDirectory(Path.Combine(root, "src", "external"), false);
|
||||
if (!Directory.Exists(Path.Combine(root, ".git")))
|
||||
{
|
||||
CloneGitRepo(root, "https://github.com/FlaxEngine/dotnet-runtime.git", null, null, true);
|
||||
GitCheckout(root, "flax-master-8");
|
||||
SetupDirectory(Path.Combine(root, "src", "external"), false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mono AOT for Windows:
|
||||
@@ -267,10 +285,10 @@ namespace Flax.Deps.Dependencies
|
||||
* .\build.cmd -c release -runtimeFlavor mono -subset mono /p:BuildMonoAotCrossCompiler=true /p:BuildMonoAOTCrossCompilerOnly=true
|
||||
*
|
||||
* Mono AOT for PS4:
|
||||
* .\build.cmd -os PS4 -a x64 /p:RuntimeOS=ps4 -c release -runtimeFlavor mono -subset mono+libs -cmakeargs "-DDISABLE_JIT=1-DENABLE_PERFTRACING=0-DDISABLE_REFLECTION_EMIT=1-DDISABLE_EVENTPIPE=1-DDISABLE_COM=1-DDISABLE_PROFILER=1-DDISABLE_COMPONENTS=1" /p:FeaturePerfTracing=false /p:FeatureManagedEtw=false /p:FeatureManagedEtwChannels=false /p:FeatureEtw=false
|
||||
* .\build.cmd -os ps4 -a x64 /p:RuntimeOS=ps4 -c release -runtimeFlavor mono -subset mono+libs -cmakeargs "-DDISABLE_JIT=1-DENABLE_PERFTRACING=0-DDISABLE_REFLECTION_EMIT=1-DDISABLE_EVENTPIPE=1-DDISABLE_COM=1-DDISABLE_PROFILER=1-DDISABLE_COMPONENTS=1" /p:FeaturePerfTracing=false /p:FeatureManagedEtw=false /p:FeatureManagedEtwChannels=false /p:FeatureEtw=false /p:ApiCompatValidateAssemblies=false
|
||||
*
|
||||
* Mono AOT cross-compiler for PS4:
|
||||
* .\build.cmd -c release -runtimeFlavor mono -subset mono /p:BuildMonoAotCrossCompiler=true /p:BuildMonoAOTCrossCompilerOnly=true /p:TargetOS=PS4 /p:HostOS=windows -cmakeargs "-DCMAKE_CROSSCOMPILING=True"
|
||||
* .\build.cmd -c release -runtimeFlavor mono -subset mono /p:BuildMonoAotCrossCompiler=true /p:BuildMonoAOTCrossCompilerOnly=true /p:TargetOS=ps4 /p:HostOS=windows -cmakeargs "-DCMAKE_CROSSCOMPILING=True"
|
||||
*/
|
||||
|
||||
foreach (var platform in options.Platforms)
|
||||
|
||||
@@ -320,6 +320,11 @@ namespace Flax.Build
|
||||
/// </summary>
|
||||
ConsoleLogOutput = 1 << 7,
|
||||
|
||||
/// <summary>
|
||||
/// Enables <see cref="ProcessStartInfo.UseShellExecute"/> to run process via Shell instead of standard process startup.
|
||||
/// </summary>
|
||||
Shell = 1 << 8,
|
||||
|
||||
/// <summary>
|
||||
/// The default options.
|
||||
/// </summary>
|
||||
@@ -398,11 +403,12 @@ namespace Flax.Build
|
||||
}
|
||||
|
||||
bool redirectStdOut = (options & RunOptions.NoStdOutRedirect) != RunOptions.NoStdOutRedirect;
|
||||
bool shell = options.HasFlag(RunOptions.Shell);
|
||||
|
||||
Process proc = new Process();
|
||||
proc.StartInfo.FileName = app;
|
||||
proc.StartInfo.Arguments = commandLine != null ? commandLine : "";
|
||||
proc.StartInfo.UseShellExecute = false;
|
||||
proc.StartInfo.UseShellExecute = shell;
|
||||
proc.StartInfo.RedirectStandardInput = input != null;
|
||||
proc.StartInfo.CreateNoWindow = true;
|
||||
|
||||
@@ -411,7 +417,7 @@ namespace Flax.Build
|
||||
proc.StartInfo.WorkingDirectory = workspace;
|
||||
}
|
||||
|
||||
if (redirectStdOut)
|
||||
if (redirectStdOut && !shell)
|
||||
{
|
||||
proc.StartInfo.RedirectStandardOutput = true;
|
||||
proc.StartInfo.RedirectStandardError = true;
|
||||
@@ -427,16 +433,24 @@ namespace Flax.Build
|
||||
}
|
||||
}
|
||||
|
||||
if (envVars != null)
|
||||
if (envVars != null && !shell)
|
||||
{
|
||||
foreach (var env in envVars)
|
||||
{
|
||||
if (env.Key == "PATH")
|
||||
{
|
||||
// Append to path
|
||||
proc.StartInfo.EnvironmentVariables[env.Key] = env.Value + ';' + proc.StartInfo.EnvironmentVariables[env.Key];
|
||||
}
|
||||
else if (env.Value == null)
|
||||
{
|
||||
// Remove variable
|
||||
if (proc.StartInfo.EnvironmentVariables.ContainsKey(env.Key))
|
||||
proc.StartInfo.EnvironmentVariables.Remove(env.Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set variable
|
||||
proc.StartInfo.EnvironmentVariables[env.Key] = env.Value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user