|
@@ -239,35 +239,22 @@ void GDMono::add_mono_shared_libs_dir_to_path() {
|
|
#endif // WINDOWS_ENABLED || UNIX_ENABLED
|
|
#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
|
|
#ifdef TOOLS_ENABLED
|
|
|
|
+
|
|
#if defined(WINDOWS_ENABLED)
|
|
#if defined(WINDOWS_ENABLED)
|
|
mono_reg_info = MonoRegUtils::find_mono();
|
|
mono_reg_info = MonoRegUtils::find_mono();
|
|
|
|
|
|
if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) {
|
|
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)) {
|
|
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)
|
|
#elif defined(OSX_ENABLED)
|
|
const char *c_assembly_rootdir = mono_assembly_getrootdir();
|
|
const char *c_assembly_rootdir = mono_assembly_getrootdir();
|
|
@@ -284,29 +271,24 @@ void GDMono::initialize() {
|
|
String hint_config_dir = path::join(locations[i], "etc");
|
|
String hint_config_dir = path::join(locations[i], "etc");
|
|
|
|
|
|
if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) {
|
|
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;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#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)) {
|
|
if (DirAccess::exists(bundled_assembly_rootdir)) {
|
|
- assembly_rootdir = bundled_assembly_rootdir;
|
|
|
|
|
|
+ r_assembly_rootdir = bundled_assembly_rootdir;
|
|
}
|
|
}
|
|
|
|
|
|
if (DirAccess::exists(bundled_config_dir)) {
|
|
if (DirAccess::exists(bundled_config_dir)) {
|
|
- config_dir = bundled_config_dir;
|
|
|
|
|
|
+ r_config_dir = bundled_config_dir;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef WINDOWS_ENABLED
|
|
#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.");
|
|
ERR_PRINT("Cannot find Mono in the registry.");
|
|
// Assertion: if they are not set, then they weren't found 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);
|
|
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
|
|
#endif // WINDOWS_ENABLED
|
|
|
|
|
|
#else
|
|
#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)
|
|
#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
|
|
// Leak if we call mono_set_dirs more than once
|
|
mono_set_dirs(assembly_rootdir.length() ? assembly_rootdir.utf8().get_data() : NULL,
|
|
mono_set_dirs(assembly_rootdir.length() ? assembly_rootdir.utf8().get_data() : NULL,
|
|
config_dir.length() ? config_dir.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();
|
|
GDMonoAndroid::register_android_dl_fallback();
|
|
#endif
|
|
#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();
|
|
GDMonoAssembly::initialize();
|
|
|
|
|
|
#if !defined(JAVASCRIPT_ENABLED)
|
|
#if !defined(JAVASCRIPT_ENABLED)
|
|
@@ -358,9 +348,12 @@ void GDMono::initialize() {
|
|
mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL);
|
|
mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL);
|
|
|
|
|
|
#ifndef TOOLS_ENABLED
|
|
#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;
|
|
return;
|
|
|
|
+ }
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#if !defined(WINDOWS_ENABLED) && !defined(NO_MONO_THREADS_SUSPEND_WORKAROUND)
|
|
#if !defined(WINDOWS_ENABLED) && !defined(NO_MONO_THREADS_SUSPEND_WORKAROUND)
|
|
@@ -475,9 +468,8 @@ void GDMono::_register_internal_calls() {
|
|
GodotSharpBindings::register_generated_icalls();
|
|
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()) {
|
|
if (get_api_core_hash() != GodotSharpBindings::get_core_api_hash()) {
|
|
ERR_PRINT("Mono: Core API hash mismatch.");
|
|
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.");
|
|
ERR_PRINT("Mono: Editor API hash mismatch.");
|
|
}
|
|
}
|
|
#endif // TOOLS_ENABLED
|
|
#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) {
|
|
void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) {
|