282 lines
12 KiB
C#
282 lines
12 KiB
C#
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Xml;
|
|
using Flax.Build;
|
|
using Flax.Build.Platforms;
|
|
using Flax.Deploy;
|
|
using System.IO.Compression;
|
|
|
|
#pragma warning disable 0219
|
|
|
|
namespace Flax.Deps.Dependencies
|
|
{
|
|
/// <summary>
|
|
/// .NET runtime
|
|
/// </summary>
|
|
/// <seealso cref="Flax.Deps.Dependency" />
|
|
class nethost : Dependency
|
|
{
|
|
/// <inheritdoc />
|
|
public override TargetPlatform[] Platforms
|
|
{
|
|
get
|
|
{
|
|
switch (BuildPlatform)
|
|
{
|
|
case TargetPlatform.Windows:
|
|
return new[]
|
|
{
|
|
TargetPlatform.PS4,
|
|
};
|
|
case TargetPlatform.Linux:
|
|
return new[]
|
|
{
|
|
TargetPlatform.Android,
|
|
};
|
|
default: return new TargetPlatform[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
private string root;
|
|
|
|
private void Build(BuildOptions options, TargetPlatform targetPlatform, TargetArchitecture architecture)
|
|
{
|
|
// Build configuration (see build.cmd -help)
|
|
string configuration = "Release";
|
|
string framework = "net7.0";
|
|
|
|
// Clean output directory
|
|
var artifacts = Path.Combine(root, "artifacts");
|
|
SetupDirectory(artifacts, true);
|
|
|
|
// Peek options
|
|
string os, arch, runtimeFlavor, subset, hostRuntimeName, buildArgsBase = string.Empty;
|
|
bool setupVersion = false;
|
|
string[] hostRuntimeFiles = Array.Empty<string>();
|
|
var envVars = new Dictionary<string, string>();
|
|
switch (architecture)
|
|
{
|
|
case TargetArchitecture.x86:
|
|
arch = "x86";
|
|
break;
|
|
case TargetArchitecture.x64:
|
|
arch = "x64";
|
|
break;
|
|
case TargetArchitecture.ARM:
|
|
arch = "arm";
|
|
break;
|
|
case TargetArchitecture.ARM64:
|
|
arch = "arm64";
|
|
break;
|
|
default: throw new InvalidArchitectureException(architecture);
|
|
}
|
|
switch (targetPlatform)
|
|
{
|
|
case TargetPlatform.Windows:
|
|
os = "windows";
|
|
runtimeFlavor = "CoreCLR";
|
|
subset = "clr";
|
|
hostRuntimeName = $"win-{arch}";
|
|
break;
|
|
case TargetPlatform.Linux:
|
|
os = "Linux";
|
|
runtimeFlavor = "CoreCLR";
|
|
subset = "clr";
|
|
hostRuntimeName = $"linux-{arch}";
|
|
break;
|
|
case TargetPlatform.Mac:
|
|
os = "OSX";
|
|
runtimeFlavor = "CoreCLR";
|
|
subset = "clr";
|
|
hostRuntimeName = $"osx-{arch}";
|
|
break;
|
|
case TargetPlatform.Android:
|
|
os = "Android";
|
|
runtimeFlavor = "Mono";
|
|
subset = "mono+libs";
|
|
hostRuntimeName = $"android-{arch}";
|
|
break;
|
|
case TargetPlatform.PS4:
|
|
os = "PS4";
|
|
runtimeFlavor = "Mono";
|
|
subset = "mono+libs";
|
|
setupVersion = true;
|
|
buildArgsBase = " /p:RuntimeOS=ps4 -cmakeargs \"-DCLR_CROSS_COMPONENTS_BUILD=1\"";
|
|
hostRuntimeName = $"ps4-{arch}";
|
|
hostRuntimeFiles = new[]
|
|
{
|
|
"coreclr_delegates.h",
|
|
"hostfxr.h",
|
|
"nethost.h",
|
|
"libnethost.a",
|
|
};
|
|
break;
|
|
default: throw new InvalidPlatformException(targetPlatform);
|
|
}
|
|
|
|
// Setup build environment variables for build system
|
|
string buildScript = null;
|
|
switch (BuildPlatform)
|
|
{
|
|
case TargetPlatform.Windows:
|
|
{
|
|
buildScript = "build.cmd";
|
|
if (setupVersion)
|
|
{
|
|
// Setup _version.c file manually
|
|
SetupDirectory(Path.Combine(artifacts, "obj"), false);
|
|
foreach (var file in new[] { "_version.c", "_version.h" })
|
|
File.Copy(Path.Combine(root, "eng", "native", "version", file), Path.Combine(artifacts, "obj", file), true);
|
|
}
|
|
var msBuild = VCEnvironment.MSBuildPath;
|
|
if (File.Exists(msBuild))
|
|
{
|
|
envVars.Add("PATH", Path.GetDirectoryName(msBuild));
|
|
}
|
|
break;
|
|
}
|
|
case TargetPlatform.Linux:
|
|
{
|
|
buildScript = "build.sh";
|
|
break;
|
|
}
|
|
case TargetPlatform.Mac:
|
|
{
|
|
buildScript = "build.sh";
|
|
break;
|
|
}
|
|
default: throw new InvalidPlatformException(BuildPlatform);
|
|
}
|
|
if (AndroidNdk.Instance.IsValid)
|
|
{
|
|
var path = AndroidNdk.Instance.RootPath;
|
|
envVars.Add("ANDROID_NDK", path);
|
|
envVars.Add("ANDROID_NDK_HOME", path);
|
|
envVars.Add("ANDROID_NDK_ROOT", path);
|
|
}
|
|
if (AndroidSdk.Instance.IsValid)
|
|
{
|
|
var path = AndroidSdk.Instance.RootPath;
|
|
envVars.Add("ANDROID_SDK", path);
|
|
envVars.Add("ANDROID_SDK_HOME", path);
|
|
envVars.Add("ANDROID_SDK_ROOT", path);
|
|
}
|
|
|
|
// Print the runtime version
|
|
string version;
|
|
{
|
|
var doc = new XmlDocument();
|
|
doc.Load(Path.Combine(root, "eng", "Versions.props"));
|
|
version = doc["Project"]["PropertyGroup"]["ProductVersion"].InnerText;
|
|
Log.Info("Building dotnet/runtime version " + version);
|
|
}
|
|
|
|
// 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";
|
|
{
|
|
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);
|
|
|
|
// Deploy build products
|
|
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",
|
|
})
|
|
{
|
|
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))
|
|
{
|
|
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", "net7.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")
|
|
{
|
|
Utilities.DirectoryCopy(Path.Combine(unpackTemp, "runtimes", hostRuntimeName, "native"), Path.Combine(dstDotnet, "native"), true, true);
|
|
Utilities.FileDelete(Path.Combine(dstDotnet, "native", privateCorelib));
|
|
}
|
|
else
|
|
throw new InvalidPlatformException(targetPlatform);
|
|
Utilities.DirectoriesDelete(unpackTemp);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override void Build(BuildOptions options)
|
|
{
|
|
root = options.IntermediateFolder;
|
|
|
|
// Ensure to have dependencies installed
|
|
Utilities.Run("ninja", "--version", null, null, Utilities.RunOptions.ThrowExceptionOnError);
|
|
Utilities.Run("cmake", "--version", null, null, Utilities.RunOptions.ThrowExceptionOnError);
|
|
|
|
// Get the source
|
|
CloneGitRepo(root, "https://github.com/FlaxEngine/dotnet-runtime.git", "flax-master", null, true);
|
|
SetupDirectory(Path.Combine(root, "src", "external"), false);
|
|
|
|
foreach (var platform in options.Platforms)
|
|
{
|
|
var platformData = Path.Combine(GetBinariesFolder(options, platform), "Data", "nethost");
|
|
if (Directory.Exists(platformData))
|
|
Utilities.DirectoryCopy(platformData, root, true, true);
|
|
switch (platform)
|
|
{
|
|
case TargetPlatform.PS4:
|
|
{
|
|
Build(options, platform, TargetArchitecture.x64);
|
|
break;
|
|
}
|
|
case TargetPlatform.Android:
|
|
{
|
|
Build(options, platform, TargetArchitecture.ARM64);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Copy license
|
|
var dstIncludePath = Path.Combine(options.ThirdPartyFolder, "nethost");
|
|
Utilities.FileCopy(Path.Combine(root, "LICENSE.TXT"), Path.Combine(dstIncludePath, "LICENSE.TXT"));
|
|
}
|
|
}
|
|
}
|