diff options
Diffstat (limited to 'modules/mono')
19 files changed, 362 insertions, 118 deletions
diff --git a/modules/mono/SCsub b/modules/mono/SCsub index a9afa7ccf6..457edfaeed 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -42,14 +42,14 @@ mono_configure.configure(env, env_mono) if env_mono['tools'] and env_mono['mono_glue']: import build_scripts.api_solution_build as api_solution_build - api_solution_build.build(env_mono) + api_sln_cmd = api_solution_build.build(env_mono) # Build GodotTools if env_mono['tools']: import build_scripts.godot_tools_build as godot_tools_build if env_mono['mono_glue']: - godot_tools_build.build(env_mono) + godot_tools_build.build(env_mono, api_sln_cmd) else: # Building without the glue sources so the Godot API solution may be missing. # GodotTools depends on the Godot API solution. As such, we will only build diff --git a/modules/mono/build_scripts/api_solution_build.py b/modules/mono/build_scripts/api_solution_build.py index 1fe00a3028..be54d0a679 100644 --- a/modules/mono/build_scripts/api_solution_build.py +++ b/modules/mono/build_scripts/api_solution_build.py @@ -55,12 +55,22 @@ def build(env_mono): 'GodotSharpEditor.dll', 'GodotSharpEditor.pdb', 'GodotSharpEditor.xml' ] + depend_cmd = [] + for build_config in ['Debug', 'Release']: output_dir = Dir('#bin').abspath editor_api_dir = os.path.join(output_dir, 'GodotSharp', 'Api', build_config) targets = [os.path.join(editor_api_dir, filename) for filename in target_filenames] - cmd = env_mono.CommandNoCache(targets, [], build_api_solution, + cmd = env_mono.CommandNoCache(targets, depend_cmd, build_api_solution, module_dir=os.getcwd(), solution_build_config=build_config) env_mono.AlwaysBuild(cmd) + + # Make the Release build of the API solution depend on the Debug build. + # We do this in order to prevent SCons from building them in parallel, + # which can freak out MSBuild. In many cases, one of the builds would + # hang indefinitely requiring a key to be pressed for it to continue. + depend_cmd = cmd + + return depend_cmd diff --git a/modules/mono/build_scripts/godot_tools_build.py b/modules/mono/build_scripts/godot_tools_build.py index 35daa6d307..03aaa925f0 100644 --- a/modules/mono/build_scripts/godot_tools_build.py +++ b/modules/mono/build_scripts/godot_tools_build.py @@ -74,15 +74,11 @@ def build_godot_tools_project_editor(source, target, env): copy_target(str(scons_target)) -def build(env_mono): +def build(env_mono, api_sln_cmd): assert env_mono['tools'] output_dir = Dir('#bin').abspath editor_tools_dir = os.path.join(output_dir, 'GodotSharp', 'Tools') - editor_api_dir = os.path.join(output_dir, 'GodotSharp', 'Api', 'Debug') - - source_filenames = ['GodotSharp.dll', 'GodotSharpEditor.dll'] - sources = [os.path.join(editor_api_dir, filename) for filename in source_filenames] target_filenames = [ 'GodotTools.dll', 'GodotTools.IdeConnection.dll', 'GodotTools.BuildLogger.dll', @@ -97,7 +93,7 @@ def build(env_mono): targets = [os.path.join(editor_tools_dir, filename) for filename in target_filenames] - cmd = env_mono.CommandNoCache(targets, sources, build_godot_tools, module_dir=os.getcwd()) + cmd = env_mono.CommandNoCache(targets, api_sln_cmd, build_godot_tools, module_dir=os.getcwd()) env_mono.AlwaysBuild(cmd) diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 5388061f84..c09690ba6d 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -120,9 +120,9 @@ def configure(env, env_mono): env.Append(LIBPATH=mono_lib_path) env_mono.Prepend(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0')) - if mono_static: - lib_suffix = Environment()['LIBSUFFIX'] + lib_suffix = Environment()['LIBSUFFIX'] + if mono_static: if env.msvc: mono_static_lib_name = 'libmono-static-sgen' else: @@ -144,13 +144,13 @@ def configure(env, env_mono): env.Append(LIBS=['psapi']) env.Append(LIBS=['version']) else: - mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib') + mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension=lib_suffix) if not mono_lib_name: raise RuntimeError('Could not find mono library in: ' + mono_lib_path) if env.msvc: - env.Append(LINKFLAGS=mono_lib_name + Environment()['LIBSUFFIX']) + env.Append(LINKFLAGS=mono_lib_name + lib_suffix) else: env.Append(LIBS=[mono_lib_name]) @@ -426,15 +426,17 @@ def copy_mono_shared_libs(env, mono_root, target_mono_root_dir): platform = env['platform'] if platform == 'windows': + src_mono_bin_dir = os.path.join(mono_root, 'bin') target_mono_bin_dir = os.path.join(target_mono_root_dir, 'bin') if not os.path.isdir(target_mono_bin_dir): os.makedirs(target_mono_bin_dir) - copy(os.path.join(mono_root, 'bin', 'MonoPosixHelper.dll'), target_mono_bin_dir) + mono_posix_helper_name = find_file_in_dir(src_mono_bin_dir, ['MonoPosixHelper', 'libMonoPosixHelper'], extension='.dll') + copy(os.path.join(src_mono_bin_dir, mono_posix_helper_name + '.dll'), os.path.join(target_mono_bin_dir, 'MonoPosixHelper.dll')) # For newer versions - btls_dll_path = os.path.join(mono_root, 'bin', 'libmono-btls-shared.dll') + btls_dll_path = os.path.join(src_mono_bin_dir, 'libmono-btls-shared.dll') if os.path.isfile(btls_dll_path): copy(btls_dll_path, target_mono_bin_dir) else: diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 34dcde40f4..4536614379 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -128,7 +128,8 @@ void CSharpLanguage::init() { print_line("Run this binary with '--generate-mono-glue path/to/modules/mono/glue'"); #endif - gdmono->initialize_load_assemblies(); + if (gdmono->is_runtime_initialized()) + gdmono->initialize_load_assemblies(); #ifdef TOOLS_ENABLED EditorNode::add_init_callback(&_editor_init_callback); diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index cf3823fd16..aed25f5ac5 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -22,6 +22,7 @@ namespace GodotTools.Export // TODO: These would be better as export preset options, but that doesn't seem to be supported yet GlobalDef("mono/export/include_scripts_content", false); + GlobalDef("mono/export/export_assemblies_inside_pck", true); GlobalDef("mono/export/aot/enabled", false); GlobalDef("mono/export/aot/full_aot", false); @@ -130,21 +131,38 @@ namespace GodotTools.Export internal_GetExportedAssemblyDependencies(projectDllName, projectDllSrcPath, buildConfig, platformBclDir, dependencies); } + string outputDataDir = null; + + if (PlatformHasTemplateDir(platform)) + outputDataDir = ExportDataDirectory(features, platform, isDebug, outputDir); + string apiConfig = isDebug ? "Debug" : "Release"; string resAssembliesDir = Path.Combine(GodotSharpDirs.ResAssembliesBaseDir, apiConfig); - foreach (var dependency in dependencies) + bool assembliesInsidePck = (bool) ProjectSettings.GetSetting("mono/export/export_assemblies_inside_pck") || outputDataDir == null; + + if (!assembliesInsidePck) { - string dependSrcPath = dependency.Value; - string dependDstPath = Path.Combine(resAssembliesDir, dependSrcPath.GetFile()); - AddFile(dependSrcPath, dependDstPath); + string outputDataGameAssembliesDir = Path.Combine(outputDataDir, "Assemblies"); + if (!Directory.Exists(outputDataGameAssembliesDir)) + Directory.CreateDirectory(outputDataGameAssembliesDir); } - // Mono specific export template extras (data dir) - string outputDataDir = null; + foreach (var dependency in dependencies) + { + string dependSrcPath = dependency.Value; - if (PlatformHasTemplateDir(platform)) - outputDataDir = ExportDataDirectory(features, platform, isDebug, outputDir); + if (assembliesInsidePck) + { + string dependDstPath = Path.Combine(resAssembliesDir, dependSrcPath.GetFile()); + AddFile(dependSrcPath, dependDstPath); + } + else + { + string dependDstPath = Path.Combine(outputDataDir, "Assemblies", dependSrcPath.GetFile()); + File.Copy(dependSrcPath, dependDstPath); + } + } // AOT diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index d0c78d095b..fb2cbabc8e 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -30,6 +30,7 @@ <ConsolePause>false</ConsolePause> </PropertyGroup> <ItemGroup> + <Reference Include="Mono.Posix" /> <Reference Include="System" /> <Reference Include="GodotSharp"> <HintPath>$(GodotSourceRootPath)/bin/GodotSharp/Api/$(GodotApiConfiguration)/GodotSharp.dll</HintPath> diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 21ee85f2a9..1a8c26acd7 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Runtime.CompilerServices; +using Mono.Unix.Native; namespace GodotTools.Utils { @@ -55,21 +56,23 @@ namespace GodotTools.Utils return name.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); } - public static bool IsWindows => IsOS(Names.Windows); - - public static bool IsOSX => IsOS(Names.OSX); - - public static bool IsX11 => IsOS(Names.X11); - - public static bool IsServer => IsOS(Names.Server); - - public static bool IsUWP => IsOS(Names.UWP); - - public static bool IsHaiku => IsOS(Names.Haiku); - - public static bool IsAndroid => IsOS(Names.Android); - - public static bool IsHTML5 => IsOS(Names.HTML5); + private static readonly Lazy<bool> _isWindows = new Lazy<bool>(() => IsOS(Names.Windows)); + private static readonly Lazy<bool> _isOSX = new Lazy<bool>(() => IsOS(Names.OSX)); + private static readonly Lazy<bool> _isX11 = new Lazy<bool>(() => IsOS(Names.X11)); + private static readonly Lazy<bool> _isServer = new Lazy<bool>(() => IsOS(Names.Server)); + private static readonly Lazy<bool> _isUWP = new Lazy<bool>(() => IsOS(Names.UWP)); + private static readonly Lazy<bool> _isHaiku = new Lazy<bool>(() => IsOS(Names.Haiku)); + private static readonly Lazy<bool> _isAndroid = new Lazy<bool>(() => IsOS(Names.Android)); + private static readonly Lazy<bool> _isHTML5 = new Lazy<bool>(() => IsOS(Names.HTML5)); + + public static bool IsWindows => _isWindows.Value; + public static bool IsOSX => _isOSX.Value; + public static bool IsX11 => _isX11.Value; + public static bool IsServer => _isServer.Value; + public static bool IsUWP => _isUWP.Value; + public static bool IsHaiku => _isHaiku.Value; + public static bool IsAndroid => _isAndroid.Value; + public static bool IsHTML5 => _isHTML5.Value; private static bool? _isUnixCache; private static readonly string[] UnixLikePlatforms = {Names.OSX, Names.X11, Names.Server, Names.Haiku, Names.Android}; @@ -88,7 +91,12 @@ namespace GodotTools.Utils public static string PathWhich(string name) { - string[] windowsExts = IsWindows ? Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) : null; + return IsWindows ? PathWhichWindows(name) : PathWhichUnix(name); + } + + private static string PathWhichWindows(string name) + { + string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? new string[] { }; string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); var searchDirs = new List<string>(); @@ -96,30 +104,34 @@ namespace GodotTools.Utils if (pathDirs != null) searchDirs.AddRange(pathDirs); + string nameExt = Path.GetExtension(name); + bool hasPathExt = string.IsNullOrEmpty(nameExt) || windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase); + searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list - foreach (var dir in searchDirs) - { - string path = Path.Combine(dir, name); - - if (IsWindows && windowsExts != null) - { - foreach (var extension in windowsExts) - { - string pathWithExtension = path + extension; - - if (File.Exists(pathWithExtension)) - return pathWithExtension; - } - } - else - { - if (File.Exists(path)) - return path; - } - } + if (hasPathExt) + return searchDirs.Select(dir => Path.Combine(dir, name)).FirstOrDefault(File.Exists); + + return (from dir in searchDirs + select Path.Combine(dir, name) + into path + from ext in windowsExts + select path + ext).FirstOrDefault(File.Exists); + } + + private static string PathWhichUnix(string name) + { + string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); + + var searchDirs = new List<string>(); + + if (pathDirs != null) + searchDirs.AddRange(pathDirs); + + searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list - return null; + return searchDirs.Select(dir => Path.Combine(dir, name)) + .FirstOrDefault(path => File.Exists(path) && Syscall.access(path, AccessModes.X_OK) == 0); } public static void RunProcess(string command, IEnumerable<string> arguments) diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index cb0ac9431e..ef30a52b72 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -108,6 +108,10 @@ public: String data_editor_tools_dir; String data_editor_prebuilt_api_dir; +#else + // Equivalent of res_assemblies_dir, but in the data directory rather than in 'res://'. + // Only defined on export templates. Used when exporting assemblies outside of PCKs. + String data_game_assemblies_dir; #endif String data_mono_etc_dir; @@ -205,6 +209,7 @@ private: data_mono_lib_dir = GDMonoAndroid::get_app_native_lib_dir(); #else data_mono_lib_dir = data_mono_root_dir.plus_file("lib"); + data_game_assemblies_dir = data_dir_root.plus_file("Assemblies"); #endif #ifdef WINDOWS_ENABLED @@ -216,6 +221,10 @@ private: data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc"); data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib"); } + + if (!DirAccess::exists(data_game_assemblies_dir)) { + data_game_assemblies_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Assemblies"); + } #endif #endif @@ -295,6 +304,10 @@ String get_data_editor_tools_dir() { String get_data_editor_prebuilt_api_dir() { return _GodotSharpDirs::get_singleton().data_editor_prebuilt_api_dir; } +#else +String get_data_game_assemblies_dir() { + return _GodotSharpDirs::get_singleton().data_game_assemblies_dir; +} #endif String get_data_mono_etc_dir() { diff --git a/modules/mono/godotsharp_dirs.h b/modules/mono/godotsharp_dirs.h index ff51888d1c..43da44b0f5 100644 --- a/modules/mono/godotsharp_dirs.h +++ b/modules/mono/godotsharp_dirs.h @@ -56,6 +56,8 @@ String get_project_csproj_path(); String get_data_editor_tools_dir(); String get_data_editor_prebuilt_api_dir(); +#else +String get_data_game_assemblies_dir(); #endif String get_data_mono_etc_dir(); diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 384ef08cd0..a43311d281 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -239,35 +239,22 @@ void GDMono::add_mono_shared_libs_dir_to_path() { #endif // WINDOWS_ENABLED || UNIX_ENABLED } -void GDMono::initialize() { - - ERR_FAIL_NULL(Engine::get_singleton()); - - print_verbose("Mono: Initializing module..."); - - char *runtime_build_info = mono_get_runtime_build_info(); - print_verbose("Mono JIT compiler version " + String(runtime_build_info)); - mono_free(runtime_build_info); - -#ifdef DEBUG_METHODS_ENABLED - _initialize_and_check_api_hashes(); -#endif +void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_dir) { - GDMonoLog::get_singleton()->initialize(); - - String assembly_rootdir; - String config_dir; + String bundled_assembly_rootdir = GodotSharpDirs::get_data_mono_lib_dir(); + String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir(); #ifdef TOOLS_ENABLED + #if defined(WINDOWS_ENABLED) mono_reg_info = MonoRegUtils::find_mono(); if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) { - assembly_rootdir = mono_reg_info.assembly_dir; + r_assembly_rootdir = mono_reg_info.assembly_dir; } if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) { - config_dir = mono_reg_info.config_dir; + r_config_dir = mono_reg_info.config_dir; } #elif defined(OSX_ENABLED) const char *c_assembly_rootdir = mono_assembly_getrootdir(); @@ -284,29 +271,24 @@ void GDMono::initialize() { String hint_config_dir = path::join(locations[i], "etc"); if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) { - assembly_rootdir = hint_assembly_rootdir; - config_dir = hint_config_dir; + r_assembly_rootdir = hint_assembly_rootdir; + r_config_dir = hint_config_dir; break; } } } #endif -#endif // TOOLS_ENABLED - String bundled_assembly_rootdir = GodotSharpDirs::get_data_mono_lib_dir(); - String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir(); - -#ifdef TOOLS_ENABLED if (DirAccess::exists(bundled_assembly_rootdir)) { - assembly_rootdir = bundled_assembly_rootdir; + r_assembly_rootdir = bundled_assembly_rootdir; } if (DirAccess::exists(bundled_config_dir)) { - config_dir = bundled_config_dir; + r_config_dir = bundled_config_dir; } #ifdef WINDOWS_ENABLED - if (assembly_rootdir.empty() || config_dir.empty()) { + if (r_assembly_rootdir.empty() || r_config_dir.empty()) { ERR_PRINT("Cannot find Mono in the registry."); // Assertion: if they are not set, then they weren't found in the registry CRASH_COND(mono_reg_info.assembly_dir.length() > 0 || mono_reg_info.config_dir.length() > 0); @@ -314,12 +296,32 @@ void GDMono::initialize() { #endif // WINDOWS_ENABLED #else - // These are always the directories in export templates - assembly_rootdir = bundled_assembly_rootdir; - config_dir = bundled_config_dir; -#endif // TOOLS_ENABLED + // Export templates always use the bundled directories + r_assembly_rootdir = bundled_assembly_rootdir; + r_config_dir = bundled_config_dir; +#endif +} + +void GDMono::initialize() { + + ERR_FAIL_NULL(Engine::get_singleton()); + + print_verbose("Mono: Initializing module..."); + + char *runtime_build_info = mono_get_runtime_build_info(); + print_verbose("Mono JIT compiler version " + String(runtime_build_info)); + mono_free(runtime_build_info); + + _init_godot_api_hashes(); + _init_exception_policy(); + + GDMonoLog::get_singleton()->initialize(); #if !defined(JAVASCRIPT_ENABLED) + String assembly_rootdir; + String config_dir; + determine_mono_dirs(assembly_rootdir, config_dir); + // Leak if we call mono_set_dirs more than once mono_set_dirs(assembly_rootdir.length() ? assembly_rootdir.utf8().get_data() : NULL, config_dir.length() ? config_dir.utf8().get_data() : NULL); @@ -331,18 +333,6 @@ void GDMono::initialize() { GDMonoAndroid::register_android_dl_fallback(); #endif - { - PropertyInfo exc_policy_prop = PropertyInfo(Variant::INT, "mono/unhandled_exception_policy", PROPERTY_HINT_ENUM, - vformat("Terminate Application:%s,Log Error:%s", (int)POLICY_TERMINATE_APP, (int)POLICY_LOG_ERROR)); - unhandled_exception_policy = (UnhandledExceptionPolicy)(int)GLOBAL_DEF(exc_policy_prop.name, (int)POLICY_TERMINATE_APP); - ProjectSettings::get_singleton()->set_custom_property_info(exc_policy_prop.name, exc_policy_prop); - - if (Engine::get_singleton()->is_editor_hint()) { - // Unhandled exceptions should not terminate the editor - unhandled_exception_policy = POLICY_LOG_ERROR; - } - } - GDMonoAssembly::initialize(); #if !defined(JAVASCRIPT_ENABLED) @@ -358,9 +348,12 @@ void GDMono::initialize() { mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL); #ifndef TOOLS_ENABLED - // Export templates only load the Mono runtime if the project uses it - if (!DirAccess::exists("res://.mono")) + // Exported games that don't use C# must still work. They likely don't ship with mscorlib. + // We only initialize the Mono runtime if we can find mscorlib. Otherwise it would crash. + if (GDMonoAssembly::find_assembly("mscorlib.dll").empty()) { + print_verbose("Mono: Skipping runtime initialization because 'mscorlib.dll' could not be found"); return; + } #endif #if !defined(WINDOWS_ENABLED) && !defined(NO_MONO_THREADS_SUSPEND_WORKAROUND) @@ -475,9 +468,8 @@ void GDMono::_register_internal_calls() { GodotSharpBindings::register_generated_icalls(); } -void GDMono::_initialize_and_check_api_hashes() { -#ifdef MONO_GLUE_ENABLED -#ifdef DEBUG_METHODS_ENABLED +void GDMono::_init_godot_api_hashes() { +#if defined(MONO_GLUE_ENABLED) && defined(DEBUG_METHODS_ENABLED) if (get_api_core_hash() != GodotSharpBindings::get_core_api_hash()) { ERR_PRINT("Mono: Core API hash mismatch."); } @@ -487,8 +479,19 @@ void GDMono::_initialize_and_check_api_hashes() { ERR_PRINT("Mono: Editor API hash mismatch."); } #endif // TOOLS_ENABLED -#endif // DEBUG_METHODS_ENABLED -#endif // MONO_GLUE_ENABLED +#endif // MONO_GLUE_ENABLED && DEBUG_METHODS_ENABLED +} + +void GDMono::_init_exception_policy() { + PropertyInfo exc_policy_prop = PropertyInfo(Variant::INT, "mono/unhandled_exception_policy", PROPERTY_HINT_ENUM, + vformat("Terminate Application:%s,Log Error:%s", (int)POLICY_TERMINATE_APP, (int)POLICY_LOG_ERROR)); + unhandled_exception_policy = (UnhandledExceptionPolicy)(int)GLOBAL_DEF(exc_policy_prop.name, (int)POLICY_TERMINATE_APP); + ProjectSettings::get_singleton()->set_custom_property_info(exc_policy_prop.name, exc_policy_prop); + + if (Engine::get_singleton()->is_editor_hint()) { + // Unhandled exceptions should not terminate the editor + unhandled_exception_policy = POLICY_LOG_ERROR; + } } void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) { diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index e14a0d8409..7fb03b82ad 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -153,7 +153,8 @@ private: #ifdef TOOLS_ENABLED uint64_t api_editor_hash; #endif - void _initialize_and_check_api_hashes(); + void _init_godot_api_hashes(); + void _init_exception_policy(); GDMonoLog *gdmono_log; @@ -162,6 +163,7 @@ private: #endif void add_mono_shared_libs_dir_to_path(); + void determine_mono_dirs(String &r_assembly_rootdir, String &r_config_dir); protected: static GDMono *singleton; diff --git a/modules/mono/mono_gd/gd_mono_android.cpp b/modules/mono/mono_gd/gd_mono_android.cpp index 42983e1821..1ee035589d 100644 --- a/modules/mono/mono_gd/gd_mono_android.cpp +++ b/modules/mono/mono_gd/gd_mono_android.cpp @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* gd_mono_android.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + #include "gd_mono_android.h" #if defined(ANDROID_ENABLED) diff --git a/modules/mono/mono_gd/gd_mono_android.h b/modules/mono/mono_gd/gd_mono_android.h index 52705fbd2d..72bc799bfd 100644 --- a/modules/mono/mono_gd/gd_mono_android.h +++ b/modules/mono/mono_gd/gd_mono_android.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* gd_mono_android.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + #ifndef GD_MONO_ANDROID_H #define GD_MONO_ANDROID_H diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 91842420b7..105560fe9a 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -62,6 +62,13 @@ void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const Strin r_search_dirs.push_back(framework_dir.plus_file("Facades")); } +#if !defined(TOOLS_ENABLED) + String data_game_assemblies_dir = GodotSharpDirs::get_data_game_assemblies_dir(); + if (!data_game_assemblies_dir.empty()) { + r_search_dirs.push_back(data_game_assemblies_dir); + } +#endif + if (p_custom_config.length()) { r_search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(p_custom_config)); } else { @@ -147,10 +154,6 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, vo (void)user_data; // UNUSED - if (search_dirs.empty()) { - fill_search_dirs(search_dirs); - } - { // If we find the assembly here, we load it with 'mono_assembly_load_from_full', // which in turn invokes load hooks before returning the MonoAssembly to us. @@ -228,6 +231,33 @@ GDMonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, cons return NULL; } +String GDMonoAssembly::find_assembly(const String &p_name) { + + String path; + + bool has_extension = p_name.ends_with(".dll") || p_name.ends_with(".exe"); + + for (int i = 0; i < search_dirs.size(); i++) { + const String &search_dir = search_dirs[i]; + + if (has_extension) { + path = search_dir.plus_file(p_name); + if (FileAccess::exists(path)) + return path; + } else { + path = search_dir.plus_file(p_name + ".dll"); + if (FileAccess::exists(path)) + return path; + + path = search_dir.plus_file(p_name + ".exe"); + if (FileAccess::exists(path)) + return path; + } + } + + return String(); +} + GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly) { GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path)); @@ -264,6 +294,8 @@ void GDMonoAssembly::_wrap_mono_assembly(MonoAssembly *assembly) { void GDMonoAssembly::initialize() { + fill_search_dirs(search_dirs); + mono_install_assembly_search_hook(&assembly_search_hook, NULL); mono_install_assembly_refonly_search_hook(&assembly_refonly_search_hook, NULL); mono_install_assembly_preload_hook(&assembly_preload_hook, NULL); diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 39749dfc1d..04a219f742 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -122,6 +122,8 @@ public: GDMonoClass *get_object_derived_class(const StringName &p_class); + static String find_assembly(const String &p_name); + static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String(), const String &p_custom_bcl_dir = String()); static GDMonoAssembly *load_from(const String &p_name, const String &p_path, bool p_refonly); diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index 3422e4ff58..caa1ca9203 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* gd_mono_cache.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + #include "gd_mono_cache.h" #include "gd_mono.h" diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 0ad7fb607c..b21f92cdd8 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* gd_mono_cache.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + #ifndef GD_MONO_CACHE_H #define GD_MONO_CACHE_H diff --git a/modules/mono/mono_gd/gd_mono_method_thunk.h b/modules/mono/mono_gd/gd_mono_method_thunk.h index 9fe9e724f2..f8cc736ec3 100644 --- a/modules/mono/mono_gd/gd_mono_method_thunk.h +++ b/modules/mono/mono_gd/gd_mono_method_thunk.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* gd_mono_method_thunk.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + #ifndef GD_MONO_METHOD_THUNK_H #define GD_MONO_METHOD_THUNK_H |