// 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 { /// /// Mono open source ECMA CLI, C# and .NET implementation. http://www.mono-project.com/ /// /// class mono : Dependency { /// public override bool BuildByDefault => false; // Unused in favor of nethost /// 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]; } } } /// public override TargetArchitecture[] Architectures { get { switch (BuildPlatform) { case TargetPlatform.Windows: return new[] { TargetArchitecture.x64, TargetArchitecture.ARM64, }; case TargetPlatform.Linux: return new[] { TargetArchitecture.x64, //TargetArchitecture.ARM64, }; case TargetPlatform.Mac: return new[] { TargetArchitecture.x64, TargetArchitecture.ARM64, }; default: return new TargetArchitecture[0]; } } } private string root; private string monoPropsPath; private string monoPreprocesorDefines; private static List 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(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); } /// 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 { { "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 { { "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 { { "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; } } } } } }