Files
FlaxEngine/Source/Tools/Flax.Build/Deps/Dependencies/mono.cs
2025-06-12 18:05:01 +02:00

807 lines
40 KiB
C#

// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using Flax.Build;
using Flax.Build.Platforms;
namespace Flax.Deps.Dependencies
{
/// <summary>
/// Mono open source ECMA CLI, C# and .NET implementation. http://www.mono-project.com/
/// </summary>
/// <seealso cref="Flax.Deps.Dependency" />
class mono : Dependency
{
/// <inheritdoc />
public override TargetPlatform[] Platforms
{
get
{
switch (BuildPlatform)
{
case TargetPlatform.Windows:
return new[]
{
TargetPlatform.Windows,
TargetPlatform.UWP,
TargetPlatform.XboxOne,
TargetPlatform.XboxScarlett,
TargetPlatform.Switch,
};
case TargetPlatform.Linux:
return new[]
{
TargetPlatform.Linux,
TargetPlatform.Android,
};
case TargetPlatform.Mac:
return new[]
{
TargetPlatform.Mac,
};
default: return new TargetPlatform[0];
}
}
}
private string root;
private string monoPropsPath;
private string monoPreprocesorDefines;
private static List<string> monoExports;
private static readonly string[] MonoExportsCustom =
{
"mono_value_box",
"mono_add_internal_call",
};
private static readonly string[] MonoExportsIncludePrefixes =
{
"mono_free",
"mono_array_",
"mono_assembly_",
"mono_class_",
"mono_custom_attrs_",
"mono_debug_",
"mono_domain_",
"mono_exception_",
"mono_field_",
"mono_free_",
"mono_gc_",
"mono_gchandle_",
"mono_get_",
"mono_image_",
"mono_metadata_",
"mono_method_",
"mono_object_",
"mono_profiler_",
"mono_property_",
"mono_raise_exception",
"mono_reflection_",
"mono_runtime_",
"mono_signature_",
"mono_stack_",
"mono_string_",
"mono_thread_",
"mono_type_",
"mono_value_",
};
private static readonly string[] MonoExportsSkipPrefixes =
{
"mono_type_to_",
"mono_thread_state_",
"mono_thread_internal_",
"mono_thread_info_",
"mono_array_get_",
"mono_array_to_byvalarray",
"mono_assembly_apply_binding",
"mono_assembly_invoke_search_hook_internal",
"mono_assembly_is_in_gac",
"mono_assembly_load_from_gac",
"mono_assembly_load_full_gac_base_default",
"mono_assembly_load_publisher_policy",
"mono_assembly_name_from_token",
"mono_assembly_remap_version",
"mono_assembly_try_decode_skip_verification",
"mono_class_create_runtime_vtable",
"mono_class_from_name_checked_aux",
"mono_class_get_appdomain_do_type_resolve_method",
"mono_class_get_exception_handling_clause_class",
"mono_class_get_field_idx",
"mono_class_get_local_variable_info_class",
"mono_class_get_pointer_class",
"mono_class_get_runtime_generic_context_template",
"mono_class_get_virtual_methods",
"mono_class_has_default_constructor",
"mono_class_has_gtd_parent",
"mono_class_has_parent",
"mono_class_implement_interface_slow",
"mono_class_is_ginst",
"mono_class_is_gtd",
"mono_class_is_interface",
"mono_class_is_magic_assembly",
"mono_class_is_valid_generic_instantiation",
"mono_class_is_variant_compatible_slow",
"mono_class_need_stelemref_method",
"mono_class_proxy_vtable",
"mono_class_setup_vtable_full",
"mono_class_try_get_unmanaged_function_pointer_attribute_class",
"mono_class_unregister_image_generic_subclasses",
"mono_custom_attrs_construct_by_type",
"mono_custom_attrs_data_construct",
"mono_debug_add_assembly",
"mono_debug_format",
"mono_debug_handles",
"mono_debug_initialized",
"mono_debug_log_thread_state_to_string",
"mono_debug_open_image",
"mono_debug_read_method",
"mono_domain_asmctx_from_path",
"mono_domain_assembly_preload",
"mono_domain_assembly_search",
"mono_domain_create_appdomain_checked",
"mono_domain_create_appdomain_internal",
"mono_domain_fire_assembly_load",
"mono_domain_fire_assembly_unload",
"mono_domain_from_appdomain_handle",
"mono_exception_new_argument_internal",
"mono_exception_new_by_name_domain",
"mono_exception_stacktrace_obj_walk",
"mono_field_get_addr",
"mono_field_get_rva",
"mono_field_resolve_flags",
"mono_free_static_data",
"mono_gc_init_finalizer_thread",
"mono_get_array_new_va_signature",
"mono_get_corlib_version",
"mono_get_domainvar",
"mono_get_exception_argument_internal",
"mono_get_exception_missing_member",
"mono_get_exception_runtime_wrapped_checked",
"mono_get_exception_type_initialization_checked",
"mono_get_field_token",
"mono_get_int_type",
"mono_get_method_from_token",
"mono_get_reflection_missing_object",
"mono_get_runtime_build_version",
"mono_get_seq_point_for_native_offset",
"mono_get_unique_iid",
"mono_get_version_info",
"mono_get_vtable_var",
"mono_get_xdomain_marshal_type",
"mono_image_add_cattrs",
"mono_image_add_decl_security",
"mono_image_add_memberef_row",
"mono_image_add_methodimpl",
"mono_image_basic_method",
"mono_image_create_method_token",
"mono_image_emit_manifest",
"mono_image_fill_export_table",
"mono_image_fill_export_table_from_class",
"mono_image_fill_export_table_from_module",
"mono_image_fill_export_table_from_type_forwarders",
"mono_image_fill_file_table",
"mono_image_fill_module_table",
"mono_image_get_array_token",
"mono_image_get_event_info",
"mono_image_get_field_info",
"mono_image_get_fieldref_token",
"mono_image_get_generic_param_info",
"mono_image_get_method_info",
"mono_image_get_methodspec_token",
"mono_image_get_property_info",
"mono_image_get_type_info",
"mono_image_walk_resource_tree",
"mono_metadata_class_equal",
"mono_metadata_field_info_full",
"mono_metadata_fnptr_equal",
"mono_metadata_generic_param_equal_internal",
"mono_metadata_parse_array_internal",
"mono_metadata_parse_generic_param",
"mono_metadata_parse_type_internal",
"mono_metadata_signature_dup_internal_with_padding",
"mono_metadata_signature_vararg_match",
"mono_method_check_inlining",
"mono_method_get_equivalent_method",
"mono_method_is_constructor",
"mono_method_is_valid_generic_instantiation",
"mono_method_is_valid_in_context",
"mono_object_new_by_vtable",
"mono_raise_exception_with_ctx",
"mono_reflection_get_type_internal",
"mono_reflection_get_type_internal_dynamic",
"mono_reflection_get_type_with_rootimage",
"mono_reflection_method_get_handle",
"mono_reflection_type_get_underlying_system_type",
"mono_runtime_capture_context",
"mono_runtime_delegate_try_invoke_handle",
"mono_runtime_set_execution_mode",
"mono_runtime_walk_stack_with_ctx",
"mono_signature_to_name",
"mono_string_builder_new",
"mono_string_from_bstr_common",
"mono_string_get_pinned",
"mono_string_is_interned_lookup",
"mono_string_new_utf32_checked",
"mono_string_to_utf8_internal",
"mono_thread_abort",
"mono_thread_abort_dummy",
"mono_thread_attach_cb",
"mono_thread_attach_internal",
"mono_thread_cleanup_fn",
"mono_thread_clear_interruption_requested",
"mono_thread_current_for_thread",
"mono_thread_detach_internal",
"mono_thread_execute_interruption",
"mono_thread_execute_interruption_ptr",
"mono_thread_execute_interruption_void",
"mono_thread_get_managed_sp",
"mono_thread_resume",
"mono_thread_set_interruption_requested",
"mono_thread_start_cb",
"mono_thread_suspend",
"mono_type_array_get_and_resolve_raw",
"mono_type_array_get_and_resolve_with_modifiers",
"mono_type_elements_shift_bits",
"mono_type_equal",
"mono_type_from_opcode",
"mono_type_get_name_recurse",
"mono_type_get_underlying_type_any",
"mono_type_hash",
"mono_type_init_lock",
"mono_type_initialization_lock",
"mono_type_is_enum_type",
"mono_type_is_native_blittable",
"mono_type_is_valid_in_context",
"mono_type_is_valid_type_in_context_full",
"mono_type_normalize",
};
private void BuildMsvc(BuildOptions options, TargetPlatform platform, TargetArchitecture architecture, string configuration = "Release")
{
string buildPlatform;
switch (architecture)
{
case TargetArchitecture.x86:
buildPlatform = "Win32";
break;
default:
buildPlatform = architecture.ToString();
break;
}
// Build mono
Deploy.VCEnvironment.BuildSolution(Path.Combine(root, "msvc", "libmono-static.vcxproj"), configuration, buildPlatform);
Deploy.VCEnvironment.BuildSolution(Path.Combine(root, "msvc", "monoposixhelper.vcxproj"), configuration, buildPlatform);
// Deploy binaries
var binaries = new[]
{
Path.Combine("lib", configuration, "libmono-static.lib"),
Path.Combine("bin", configuration, "MonoPosixHelper.dll"),
};
var srcBinaries = Path.Combine(root, "msvc", "build", "sgen", buildPlatform);
var depsFolder = GetThirdPartyFolder(options, platform, architecture);
Log.Verbose("Copy mono binaries from " + srcBinaries);
foreach (var binary in binaries)
{
var src = Path.Combine(srcBinaries, binary);
var dst = Path.Combine(depsFolder, Path.GetFileName(src));
Utilities.FileCopy(src, dst);
}
// Deploy debug symbols
var debugSymbolsLibs = new[]
{
"libmonoruntime",
"libmonoutils",
"libgcmonosgen",
"libmini",
"eglib",
};
foreach (var debugSymbol in debugSymbolsLibs)
{
var src = Path.Combine(srcBinaries, "obj", debugSymbol, configuration, debugSymbol + ".pdb");
var dst = Path.Combine(depsFolder, Path.GetFileName(src));
Utilities.FileCopy(src, dst);
}
}
private void BuildBcl(BuildOptions options, TargetPlatform platform)
{
var configuration = "Release";
string buildPlatform;
switch (platform)
{
case TargetPlatform.Android:
buildPlatform = "monodroid";
break;
case TargetPlatform.PS4:
buildPlatform = "orbis";
break;
default:
buildPlatform = "net_4_x";
break;
}
// Build jay
Deploy.VCEnvironment.BuildSolution(Path.Combine(root, "mcs", "jay", "jay.vcxproj"), "Release", "x64");
// Build class library
Utilities.Run(Deploy.VCEnvironment.CscPath, "prepare.cs", null, Path.Combine(root, "msvc", "scripts"));
Utilities.Run(Path.Combine(root, "msvc", "scripts", "prepare.exe"), "..\\..\\mcs core", null, Path.Combine(root, "msvc", "scripts"));
Deploy.VCEnvironment.BuildSolution(Path.Combine(root, "bcl.sln"), configuration, buildPlatform);
}
private static void ReplaceXmlNodeValue(XmlNode node, string name, string value)
{
foreach (XmlNode child in node.ChildNodes)
{
if (child.Name == name)
{
child.InnerText = value;
}
ReplaceXmlNodeValue(child, name, value);
}
}
protected static string FindXmlNodeValue(XmlNode node, string name)
{
foreach (XmlNode child in node.ChildNodes)
{
if (child.Name == name)
{
return child.InnerText;
}
var value = FindXmlNodeValue(child, name);
if (value != null)
return value;
}
return null;
}
protected void ConfigureMsvc(BuildOptions options, string vcTools, string winSdkVer, string winVer = "0x0601", string customDefines = null)
{
// Patch vcxproj files
var files = Directory.GetFiles(Path.Combine(root, "msvc"), "*.vcxproj", SearchOption.TopDirectoryOnly);
foreach (var file in files)
{
var projectXml = new XmlDocument();
projectXml.Load(file);
ReplaceXmlNodeValue(projectXml, "PlatformToolset", vcTools);
ReplaceXmlNodeValue(projectXml, "WindowsTargetPlatformVersion", winSdkVer);
projectXml.Save(file);
}
// Patch mono.props
{
var defines = monoPreprocesorDefines.Replace("WINVER=0x0601", "WINVER=" + winVer);
defines = defines.Replace("_WIN32_WINNT=0x0601", "_WIN32_WINNT=" + winVer);
if (customDefines != null)
{
defines = customDefines + ';' + defines;
}
var monoProps = new XmlDocument();
monoProps.Load(monoPropsPath);
ReplaceXmlNodeValue(monoProps, "MONO_PREPROCESSOR_DEFINITIONS", defines);
monoProps.Save(monoPropsPath);
}
}
private static bool EnumSymbols(string name, ulong address, uint size, IntPtr context)
{
if (name.StartsWith("mono_") && !monoExports.Contains(name))
{
if (MonoExportsIncludePrefixes.Any(name.StartsWith) && !MonoExportsSkipPrefixes.Any(name.StartsWith))
{
monoExports.Add(name);
}
}
return true;
}
private void GetMonoExports(BuildOptions options)
{
// Search for all exported mono API functions from mono library
monoExports = new List<string>(2048);
monoExports.AddRange(MonoExportsCustom);
IntPtr hCurrentProcess = Process.GetCurrentProcess().Handle;
bool status = WinAPI.dbghelp.SymInitialize(hCurrentProcess, null, false);
if (status == false)
{
Log.Error("Failed to initialize Sym.");
return;
}
string dllPath = Path.Combine(root, "msvc\\build\\sgen\\x64\\bin\\Release\\mono-2.0.dll");
ulong baseOfDll = WinAPI.dbghelp.SymLoadModuleEx(hCurrentProcess, IntPtr.Zero, dllPath, null, 0, 0, IntPtr.Zero, 0);
if (baseOfDll == 0)
{
Log.Error($"Failed to load mono library for exports from \'{dllPath}\'.");
WinAPI.dbghelp.SymCleanup(hCurrentProcess);
return;
}
if (WinAPI.dbghelp.SymEnumerateSymbols64(hCurrentProcess, baseOfDll, EnumSymbols, IntPtr.Zero) == false)
{
Log.Error($"Failed to enumerate mono library exports from \'{dllPath}\'.");
}
WinAPI.dbghelp.SymCleanup(hCurrentProcess);
// Make exports list stable
monoExports.Sort();
// Generate exports code
var exports = new StringBuilder(monoExports.Count * 70);
foreach (var monoExport in monoExports)
{
exports.AppendLine(string.Format("#pragma comment(linker, \"/export:{0}\")", monoExport));
}
// Update source file with exported symbols
var mCorePath = Path.Combine(Globals.EngineRoot, "Source", "Engine", "Scripting", "Runtime", "Mono.cpp");
var contents = File.ReadAllText(mCorePath);
var startPos = contents.IndexOf("#pragma comment(linker,");
var endPos = contents.LastIndexOf("#pragma comment(linker,");
endPos = contents.IndexOf(')', endPos);
contents = contents.Remove(startPos, endPos - startPos + 3);
contents = contents.Insert(startPos, exports.ToString());
Utilities.WriteFileIfChanged(mCorePath, contents);
}
private void DeployDylib(string srcPath, string dstFolder)
{
var dstPath = Path.Combine(dstFolder, Path.GetFileName(srcPath));
Utilities.FileCopy(srcPath, dstPath);
MacPlatform.FixInstallNameId(dstPath);
}
/// <inheritdoc />
public override void Build(BuildOptions options)
{
// Set it to the local path of the mono rep oto use for the build instead of cloning the remote one (helps with rapid testing)
string localRepoPath = string.Empty;
//localRepoPath = @"D:\Flax\3rdParty\mono";
root = options.IntermediateFolder;
if (!string.IsNullOrEmpty(localRepoPath))
root = localRepoPath;
monoPropsPath = Path.Combine(root, "msvc", "mono.props");
// Get the source
if (string.IsNullOrEmpty(localRepoPath))
CloneGitRepo(root, "https://github.com/FlaxEngine/mono.git", null, "--recursive");
// Get the default preprocessor defines for Mono on Windows-based platforms
{
var monoProps = new XmlDocument();
monoProps.Load(monoPropsPath);
monoPreprocesorDefines = FindXmlNodeValue(monoProps, "MONO_PREPROCESSOR_DEFINITIONS");
}
foreach (var platform in options.Platforms)
{
// Pick a proper branch
var monoBranch = "flax-master-5-20";
switch (platform)
{
case TargetPlatform.Switch:
case TargetPlatform.Mac:
monoBranch = "flax-master-6-4";
break;
}
GitCheckout(root, monoBranch);
GitResetLocalChanges(root);
switch (platform)
{
case TargetPlatform.Windows:
{
var configuration = "Release";
BuildMsvc(options, platform, TargetArchitecture.x64, configuration);
//BuildBcl(options, platform);
// Export header files
Deploy.VCEnvironment.BuildSolution(Path.Combine(root, "msvc", "libmono-dynamic.vcxproj"), configuration, "x64");
Deploy.VCEnvironment.BuildSolution(Path.Combine(root, "msvc", "build-install.vcxproj"), configuration, "x64");
// Get exported mono methods to forward them in engine module (on Win32 platforms)
GetMonoExports(options);
if (BuildPlatform == TargetPlatform.Windows)
{
// Copy header files
var dstIncludePath = Path.Combine(options.ThirdPartyFolder, "mono-2.0");
var dstMonoIncludePath = Path.Combine(dstIncludePath, "mono");
if (Directory.Exists(dstMonoIncludePath))
Directory.Delete(dstMonoIncludePath, true);
Utilities.DirectoryCopy(Path.Combine(root, "msvc", "include"), dstIncludePath);
}
break;
}
case TargetPlatform.UWP:
{
ConfigureMsvc(options, "v141", "10.0.17763.0", "0x0A00", "_UWP=1;DISABLE_JIT;WINAPI_FAMILY=WINAPI_FAMILY_PC_APP;HAVE_EXTERN_DEFINED_WINAPI_SUPPORT");
BuildMsvc(options, platform, TargetArchitecture.x64);
break;
}
case TargetPlatform.Linux:
{
var envVars = new Dictionary<string, string>
{
{ "CC", "clang-" + Configuration.LinuxClangMinVer },
{ "CXX", "clang++-" + Configuration.LinuxClangMinVer }
};
var monoOptions = new[]
{
"--with-xen-opt=no",
"--without-ikvm-native",
"--disable-boehm",
//"--disable-mcs-build",
"--with-mcs-docs=no",
//"--enable-static",
};
var buildDir = Path.Combine(root, "build-linux");
// Build mono
SetupDirectory(buildDir, true);
var archName = UnixToolchain.GetToolchainName(platform, TargetArchitecture.x64);
Utilities.Run(Path.Combine(root, "autogen.sh"), string.Format("--host={0} --prefix={1} {2}", archName, buildDir, string.Join(" ", monoOptions)), null, root, Utilities.RunOptions.Default, envVars);
Utilities.Run("make", null, null, root, Utilities.RunOptions.None, envVars);
Utilities.Run("make", "install", null, root, Utilities.RunOptions.None, envVars);
// Deploy binaries
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
Utilities.FileCopy(Path.Combine(buildDir, "lib", "libmonosgen-2.0.so.1.0.0"), Path.Combine(depsFolder, "libmonosgen-2.0.so.1.0.0"));
var gameLibOutput = Path.Combine(options.PlatformsFolder, "Linux", "Binaries", "Mono", "lib");
Utilities.FileCopy(Path.Combine(buildDir, "lib", "libMonoPosixHelper.so"), Path.Combine(gameLibOutput, "libMonoPosixHelper.so"));
Utilities.FileCopy(Path.Combine(buildDir, "lib", "libmono-native.so"), Path.Combine(gameLibOutput, "libmono-native.so"));
var editorLibOutput = Path.Combine(options.PlatformsFolder, "Editor", "Linux", "Mono", "lib");
Utilities.FileCopy(Path.Combine(buildDir, "lib", "libMonoPosixHelper.so"), Path.Combine(editorLibOutput, "libMonoPosixHelper.so"));
Utilities.FileCopy(Path.Combine(buildDir, "lib", "libmono-native.so"), Path.Combine(editorLibOutput, "libmono-native.so"));
var editoBinOutput = Path.Combine(options.PlatformsFolder, "Editor", "Linux", "Mono", "bin");
Utilities.FileCopy(Path.Combine(buildDir, "bin", "mono-sgen"), Path.Combine(editoBinOutput, "mono"));
Utilities.Run("strip", "mono", null, editoBinOutput, Utilities.RunOptions.None);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "Mono", "etc"), true, true);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(options.PlatformsFolder, "Editor", platform.ToString(), "Binaries", "Mono", "etc"), true, true);
var srcMonoLibs = Path.Combine(buildDir, "lib", "mono");
var dstMonoLibs = Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "Mono", "lib", "mono");
var dstMonoEditorLibs = Path.Combine(options.PlatformsFolder, "Editor", platform.ToString(), "Mono", "lib", "mono");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "4.5"), Path.Combine(dstMonoLibs, "4.5"), false, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "4.5"), Path.Combine(dstMonoEditorLibs, "4.5"), false, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "gac"), Path.Combine(dstMonoLibs, "gac"), true, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "gac"), Path.Combine(dstMonoEditorLibs, "gac"), true, true, "*.dll");
Utilities.FileCopy(Path.Combine(srcMonoLibs, "4.5", "csc.exe"), Path.Combine(dstMonoEditorLibs, "4.5", "csc.exe"), true);
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "4.5", "Facades"), Path.Combine(dstMonoEditorLibs, "4.5", "Facades"), false, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "4.5-api"), Path.Combine(dstMonoEditorLibs, "4.5-api"), false, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "xbuild", "14.0"), Path.Combine(dstMonoEditorLibs, "xbuild", "14.0"), true, true);
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "xbuild-frameworks", ".NETFramework", "v4.5"), Path.Combine(dstMonoEditorLibs, "xbuild-frameworks", ".NETFramework", "v4.5"), true, true);
Utilities.FilesDelete(dstMonoLibs, "*.pdb", true);
Utilities.FilesDelete(dstMonoEditorLibs, "*.pdb", true);
break;
}
case TargetPlatform.XboxOne:
{
ConfigureMsvc(options, "v142", "10.0.19041.0", "0x0A00", "_XBOX_ONE=1;DISABLE_JIT;WINAPI_FAMILY=WINAPI_FAMILY_GAMES;HAVE_EXTERN_DEFINED_WINAPI_SUPPORT;CRITICAL_SECTION_NO_DEBUG_INFO=0x01000000");
BuildMsvc(options, platform, TargetArchitecture.x64);
break;
}
case TargetPlatform.XboxScarlett:
{
ConfigureMsvc(options, "v142", "10.0.19041.0", "0x0A00", "_XBOX_ONE=1;DISABLE_JIT;WINAPI_FAMILY=WINAPI_FAMILY_GAMES;HAVE_EXTERN_DEFINED_WINAPI_SUPPORT;CRITICAL_SECTION_NO_DEBUG_INFO=0x01000000");
BuildMsvc(options, platform, TargetArchitecture.x64);
break;
}
case TargetPlatform.Android:
{
var sdk = AndroidSdk.Instance.RootPath;
var ndk = AndroidNdk.Instance.RootPath;
var apiLevel = Configuration.AndroidPlatformApi.ToString();
var archName = UnixToolchain.GetToolchainName(platform, TargetArchitecture.ARM64);
var toolchainRoot = Path.Combine(ndk, "toolchains", "llvm", "prebuilt", AndroidSdk.GetHostName());
var ndkBin = Path.Combine(toolchainRoot, "bin");
var compilerFlags = string.Format("-DANDROID -DMONODROID=1 -DANDROID64 -D__ANDROID_API__={0} --sysroot=\"{1}/sysroot\" --gcc-toolchain=\"{1}\"", apiLevel, toolchainRoot);
var envVars = new Dictionary<string, string>
{
{ "ANDROID_SDK_ROOT", sdk },
{ "ANDROID_SDK", sdk },
{ "ANDROID_NDK_ROOT", ndk },
{ "ANDROID_NDK", ndk },
{ "NDK", ndk },
{ "NDK_BIN", ndkBin },
{ "ANDROID_PLATFORM", "android-" + apiLevel },
{ "ANDROID_API", apiLevel },
{ "ANDROID_API_VERSION", apiLevel },
{ "ANDROID_NATIVE_API_LEVEL", apiLevel },
{ "CC", Path.Combine(ndkBin, archName + apiLevel + "-clang") },
{ "CXX", Path.Combine(ndkBin, archName + apiLevel + "-clang++") },
{ "AR", Path.Combine(ndkBin, archName + "-ar") },
{ "AS", Path.Combine(ndkBin, archName + "-as") },
{ "LD", Path.Combine(ndkBin, archName + "-ld") },
{ "RANLIB", Path.Combine(ndkBin, archName + "-ranlib") },
{ "STRIP", Path.Combine(ndkBin, archName + "-strip") },
{ "SYSROOT", toolchainRoot },
{ "CFLAGS", compilerFlags },
{ "CXXFLAGS", compilerFlags },
{ "CPPFLAGS", compilerFlags },
};
var monoOptions = new[]
{
"--disable-crash-reporting",
"--disable-executables",
"--disable-iconv",
"--disable-boehm",
"--disable-nls",
"--disable-mcs-build",
"--enable-maintainer-mode",
"--enable-dynamic-btls",
"--enable-monodroid",
"--with-btls-android-ndk",
"--with-sigaltstack=yes",
string.Format("--with-btls-android-ndk={0}", ndk),
string.Format("--with-btls-android-api={0}", apiLevel),
string.Format("--with-btls-android-cmake-toolchain={0}/build/cmake/android.toolchain.cmake", ndk),
"--without-ikvm-native",
};
var binaries = new[]
{
"lib/libmonosgen-2.0.so",
};
var buildDir = Path.Combine(root, "build-android");
var envArgs = "";
foreach (var e in envVars)
{
if (e.Value.Contains(' '))
envArgs += $" \"{e.Key}={e.Value}\"";
else
envArgs += $" {e.Key}={e.Value}";
}
// Compile mono
SetupDirectory(buildDir, true);
var toolchain = UnixToolchain.GetToolchainName(platform, TargetArchitecture.ARM64);
Utilities.Run(Path.Combine(root, "autogen.sh"), string.Format("--host={0} --prefix={1} {2}{3}", toolchain, buildDir, string.Join(" ", monoOptions), envArgs), null, root, Utilities.RunOptions.Default, envVars);
Utilities.Run("make", null, null, root, Utilities.RunOptions.None, envVars);
Utilities.Run("make", "install", null, root, Utilities.RunOptions.None, envVars);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.ARM64);
foreach (var binary in binaries)
{
var src = Path.Combine(buildDir, binary);
var dst = Path.Combine(depsFolder, Path.GetFileName(binary));
Utilities.FileCopy(src, dst);
}
// Clean before another build
GitResetLocalChanges(root);
Utilities.Run("make", "distclean", null, root, Utilities.RunOptions.None);
// Compile BCL
var installBcl = Path.Combine(root, "bcl-android");
var bclOutput = Path.Combine(GetBinariesFolder(options, platform), "Mono");
var bclLibOutput = Path.Combine(bclOutput, "lib");
var bclLibMonoOutput = Path.Combine(bclLibOutput, "mono");
SetupDirectory(installBcl, true);
SetupDirectory(bclOutput, true);
SetupDirectory(bclLibOutput, false);
SetupDirectory(bclLibMonoOutput, false);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(bclOutput, "etc"), true, true);
Utilities.FileCopy(Path.Combine(buildDir, "lib", "libMonoPosixHelper.so"), Path.Combine(bclLibOutput, "libMonoPosixHelper.so"));
Utilities.FileCopy(Path.Combine(buildDir, "lib", "libmono-native.so"), Path.Combine(bclLibOutput, "libmono-native.so"));
Utilities.FileCopy(Path.Combine(buildDir, "lib", "libmono-btls-shared.so"), Path.Combine(bclLibOutput, "libmono-btls-shared.so"));
var bclOptions = new[]
{
"--disable-boehm",
"--disable-btls-lib",
"--disable-nls",
"--disable-support-build",
"--with-mcs-docs=no",
};
Utilities.Run(Path.Combine(root, "autogen.sh"), string.Format("--prefix={0} {1}", installBcl, string.Join(" ", bclOptions)), null, root);
Utilities.Run("make", $"-j1 -C {root} -C mono", null, root, Utilities.RunOptions.None);
Utilities.Run("make", $"-j2 -C {root} -C runtime all-mcs build_profiles=monodroid", null, root, Utilities.RunOptions.None);
Utilities.DirectoryCopy(Path.Combine(root, "mcs", "class", "lib", "monodroid"), Path.Combine(bclLibMonoOutput, "2.1"), true, true, "*.dll");
Utilities.DirectoryDelete(Path.Combine(bclLibMonoOutput, "2.1", "Facades"));
break;
}
case TargetPlatform.Switch:
{
var type = Type.GetType("Flax.Build.Platforms.Switch.mono");
var method = type.GetMethod("Build");
method.Invoke(null, new object[] { root, options });
break;
}
case TargetPlatform.Mac:
{
var compilerFlags = string.Format("-mmacosx-version-min={0}", Configuration.MacOSXMinVer);
var envVars = new Dictionary<string, string>
{
{ "CFLAGS", compilerFlags },
{ "CXXFLAGS", compilerFlags },
{ "CPPFLAGS", compilerFlags },
};
var monoOptions = new[]
{
"--with-xen-opt=no",
"--without-ikvm-native",
"--disable-boehm",
"--disable-nls",
"--disable-iconv",
//"--disable-mcs-build",
"--with-mcs-docs=no",
"--with-tls=pthread",
//"--enable-static",
"--enable-maintainer-mode",
};
var buildDir = Path.Combine(root, "build-mac");
// Build mono
SetupDirectory(buildDir, true);
var archName = "x86_64-apple-darwin19";
Utilities.Run(Path.Combine(root, "autogen.sh"), string.Format("--host={0} --prefix={1} {2}", archName, buildDir, string.Join(" ", monoOptions)), null, root, Utilities.RunOptions.None, envVars);
Utilities.Run("make", null, null, root, Utilities.RunOptions.None, envVars);
Utilities.Run("make", "install", null, root, Utilities.RunOptions.None, envVars);
// Deploy binaries
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
Directory.CreateDirectory(depsFolder);
DeployDylib(Path.Combine(buildDir, "lib", "libmonosgen-2.0.1.dylib"), depsFolder);
var gameLibOutput = Path.Combine(options.PlatformsFolder, "Mac", "Binaries", "Mono", "lib");
Directory.CreateDirectory(gameLibOutput);
DeployDylib(Path.Combine(buildDir, "lib", "libMonoPosixHelper.dylib"), gameLibOutput);
DeployDylib(Path.Combine(buildDir, "lib", "libmono-btls-shared.dylib"), gameLibOutput);
DeployDylib(Path.Combine(buildDir, "lib", "libmono-native.dylib"), gameLibOutput);
var editorLibOutput = Path.Combine(options.PlatformsFolder, "Editor", "Mac", "Mono", "lib");
Directory.CreateDirectory(editorLibOutput);
DeployDylib(Path.Combine(buildDir, "lib", "libMonoPosixHelper.dylib"), editorLibOutput);
DeployDylib(Path.Combine(buildDir, "lib", "libmono-btls-shared.dylib"), editorLibOutput);
DeployDylib(Path.Combine(buildDir, "lib", "libmono-native.dylib"), editorLibOutput);
var editoBinOutput = Path.Combine(options.PlatformsFolder, "Editor", "Mac", "Mono", "bin");
Directory.CreateDirectory(editoBinOutput);
Utilities.FileCopy(Path.Combine(buildDir, "bin", "mono-sgen"), Path.Combine(editoBinOutput, "mono"));
Utilities.Run("strip", "mono", null, editoBinOutput, Utilities.RunOptions.None);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "Mono", "etc"), true, true);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(options.PlatformsFolder, "Editor", platform.ToString(), "Binaries", "Mono", "etc"), true, true);
var srcMonoLibs = Path.Combine(buildDir, "lib", "mono");
var dstMonoLibs = Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "Mono", "lib", "mono");
var dstMonoEditorLibs = Path.Combine(options.PlatformsFolder, "Editor", platform.ToString(), "Mono", "lib", "mono");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "4.5"), Path.Combine(dstMonoLibs, "4.5"), false, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "4.5"), Path.Combine(dstMonoEditorLibs, "4.5"), false, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "gac"), Path.Combine(dstMonoLibs, "gac"), true, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "gac"), Path.Combine(dstMonoEditorLibs, "gac"), true, true, "*.dll");
Utilities.FileCopy(Path.Combine(srcMonoLibs, "4.5", "csc.exe"), Path.Combine(dstMonoEditorLibs, "4.5", "csc.exe"), true);
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "4.5", "Facades"), Path.Combine(dstMonoEditorLibs, "4.5", "Facades"), false, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "4.5-api"), Path.Combine(dstMonoEditorLibs, "4.5-api"), false, true, "*.dll");
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "xbuild", "14.0"), Path.Combine(dstMonoEditorLibs, "xbuild", "14.0"), true, true);
Utilities.DirectoryCopy(Path.Combine(srcMonoLibs, "xbuild-frameworks", ".NETFramework", "v4.5"), Path.Combine(dstMonoEditorLibs, "xbuild-frameworks", ".NETFramework", "v4.5"), true, true);
Utilities.FilesDelete(dstMonoLibs, "*.pdb", true);
Utilities.FilesDelete(dstMonoEditorLibs, "*.pdb", true);
break;
}
}
}
}
}
}