Merge pull request #29359 from neikeq/android-mono

Android build and export for the mono module
This commit is contained in:
Rémi Verschelde 2019-06-03 18:06:07 +02:00 committed by GitHub
commit 42569f566f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 238 additions and 122 deletions

View File

@ -1,6 +1,5 @@
# Build GodotSharpTools solution
import os
from SCons.Script import Builder, Dir
@ -53,21 +52,9 @@ def find_nuget_windows(env):
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
return hint_path
from . import mono_reg_utils as monoreg
from . mono_reg_utils import find_mono_root_dir
mono_root = ''
bits = env['bits']
if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
else:
mono_root = monoreg.find_mono_root_dir(bits)
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')
else:
mono_root = monoreg.find_mono_root_dir(bits)
mono_root = env['mono_prefix'] or find_mono_root_dir(env['bits'])
if mono_root:
mono_bin_dir = os.path.join(mono_root, 'bin')
@ -114,21 +101,9 @@ def find_msbuild_unix(filename):
def find_msbuild_windows(env):
from . import mono_reg_utils as monoreg
from . mono_reg_utils import find_mono_root_dir, find_msbuild_tools_path_reg
mono_root = ''
bits = env['bits']
if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
else:
mono_root = monoreg.find_mono_root_dir(bits)
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')
else:
mono_root = monoreg.find_mono_root_dir(bits)
mono_root = env['mono_prefix'] or find_mono_root_dir(env['bits'])
if not mono_root:
raise RuntimeError('Cannot find mono root directory')
@ -148,7 +123,7 @@ def find_msbuild_windows(env):
}
return (msbuild_mono, framework_path, mono_msbuild_env)
msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
msbuild_tools_path = find_msbuild_tools_path_reg()
if msbuild_tools_path:
return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), framework_path, {})

View File

@ -1,15 +1,30 @@
import imp
import os
import os.path
import sys
import subprocess
from distutils.version import LooseVersion
from SCons.Script import BoolVariable, Dir, Environment, Variables
from SCons.Script import Dir, Environment
if os.name == 'nt':
from . import mono_reg_utils as monoreg
android_arch_dirs = {
'armv7': 'armeabi-v7a',
'arm64v8': 'arm64-v8a',
'x86': 'x86',
'x86_64': 'x86_64'
}
def get_android_out_dir(env):
return os.path.join(Dir('#platform/android/java/libs').abspath,
'release' if env['target'] == 'release' else 'debug',
android_arch_dirs[env['android_arch']])
def find_file_in_dir(directory, files, prefix='', extension=''):
if not extension.startswith('.'):
extension = '.' + extension
@ -20,47 +35,55 @@ def find_file_in_dir(directory, files, prefix='', extension=''):
def copy_file(src_dir, dst_dir, name):
from shutil import copyfile
from shutil import copy
src_path = os.path.join(src_dir, name)
dst_path = os.path.join(dst_dir, name)
src_path = os.path.join(Dir(src_dir).abspath, name)
dst_dir = Dir(dst_dir).abspath
if not os.path.isdir(dst_dir):
os.mkdir(dst_dir)
copyfile(src_path, dst_path)
copy(src_path, dst_dir)
def configure(env, env_mono):
from SCons.Script import BoolVariable, PathVariable, Variables
envvars = Variables()
envvars.Add(PathVariable('mono_prefix', 'Path to the mono installation directory for the target platform and architecture', '', PathVariable.PathAccept))
envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False))
envvars.Update(env)
bits = env['bits']
is_android = env['platform'] == 'android'
tools_enabled = env['tools']
mono_static = env['mono_static']
copy_mono_root = env['copy_mono_root']
mono_prefix = env['mono_prefix']
mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
if env['platform'] == 'windows':
mono_root = ''
if is_android and not env['android_arch'] in android_arch_dirs:
raise RuntimeError('This module does not support for the specified \'android_arch\': ' + env['android_arch'])
if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
elif os.name == 'nt':
mono_root = monoreg.find_mono_root_dir(bits)
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')
elif os.name == 'nt':
mono_root = monoreg.find_mono_root_dir(bits)
if is_android and tools_enabled:
# TODO: Implement this. We have to add the data directory to the apk, concretely the Api and Tools folders.
raise RuntimeError('This module does not currently support building for android with tools enabled')
if (os.getenv('MONO32_PREFIX') or os.getenv('MONO64_PREFIX')) and not mono_prefix:
print("WARNING: The environment variables 'MONO32_PREFIX' and 'MONO64_PREFIX' are deprecated; use the 'mono_prefix' SCons parameter instead")
if env['platform'] == 'windows':
mono_root = mono_prefix
if not mono_root and os.name == 'nt':
mono_root = monoreg.find_mono_root_dir(bits)
if not mono_root:
raise RuntimeError('Mono installation directory not found')
raise RuntimeError("Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter")
print('Found Mono root directory: ' + mono_root)
@ -113,21 +136,18 @@ def configure(env, env_mono):
if not mono_dll_name:
raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)
copy_file(mono_bin_path, 'bin', mono_dll_name + '.dll')
copy_file(mono_bin_path, '#bin', mono_dll_name + '.dll')
else:
is_apple = (sys.platform == 'darwin' or "osxcross" in env)
sharedlib_ext = '.dylib' if is_apple else '.so'
mono_root = ''
mono_root = mono_prefix
mono_lib_path = ''
mono_so_name = ''
if bits == '32':
if os.getenv('MONO32_PREFIX'):
mono_root = os.getenv('MONO32_PREFIX')
else:
if os.getenv('MONO64_PREFIX'):
mono_root = os.getenv('MONO64_PREFIX')
if not mono_root and is_android:
raise RuntimeError("Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter")
if not mono_root and is_apple:
# Try with some known directories under OSX
@ -142,7 +162,8 @@ def configure(env, env_mono):
if not mono_root and mono_static:
mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext)
if not mono_root:
raise RuntimeError('Building with mono_static=yes, but failed to find the mono prefix with pkg-config. Specify one manually')
raise RuntimeError("Building with mono_static=yes, but failed to find the mono prefix with pkg-config; " + \
"specify one manually with the 'mono_prefix' SCons parameter")
if mono_root:
print('Found Mono root directory: ' + mono_root)
@ -174,6 +195,8 @@ def configure(env, env_mono):
if is_apple:
env.Append(LIBS=['iconv', 'pthread'])
elif is_android:
env.Append(LIBS=['m', 'dl'])
else:
env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
@ -183,7 +206,7 @@ def configure(env, env_mono):
if not mono_so_name:
raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path)
copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
copy_file(mono_lib_path, '#bin', 'lib' + mono_so_name + sharedlib_ext)
else:
assert not mono_static
@ -196,9 +219,6 @@ def configure(env, env_mono):
env.ParseConfig('pkg-config monosgen-2 --libs')
env_mono.ParseConfig('pkg-config monosgen-2 --cflags')
mono_lib_path = ''
mono_so_name = ''
tmpenv = Environment()
tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
@ -213,11 +233,13 @@ def configure(env, env_mono):
if not mono_so_name:
raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH']))
copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
if not mono_static:
libs_output_dir = get_android_out_dir(env) if is_android else '#bin'
copy_file(mono_lib_path, libs_output_dir, 'lib' + mono_so_name + sharedlib_ext)
env.Append(LINKFLAGS='-rdynamic')
if not tools_enabled:
if not tools_enabled and not is_android:
if not mono_root:
mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
@ -241,7 +263,7 @@ def make_template_dir(env, mono_root):
template_dir_name = ''
if platform in ['windows', 'osx', 'x11']:
if platform in ['windows', 'osx', 'x11', 'android']:
template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target)
else:
assert False
@ -256,12 +278,13 @@ def make_template_dir(env, mono_root):
# Copy etc/mono/
template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono')
copy_mono_etc_dir(mono_root, template_mono_config_dir, env['platform'])
if platform != 'android':
template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono')
copy_mono_etc_dir(mono_root, template_mono_config_dir, env['platform'])
# Copy the required shared libraries
copy_mono_shared_libs(mono_root, template_mono_root_dir, env['platform'])
copy_mono_shared_libs(env, mono_root, template_mono_root_dir)
def copy_mono_root_files(env, mono_root):
@ -285,7 +308,7 @@ def copy_mono_root_files(env, mono_root):
# Copy the required shared libraries
copy_mono_shared_libs(mono_root, editor_mono_root_dir, env['platform'])
copy_mono_shared_libs(env, mono_root, editor_mono_root_dir)
# Copy framework assemblies
@ -332,39 +355,55 @@ def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform):
copy_tree(os.path.join(mono_etc_dir, '2.0'), os.path.join(target_mono_config_dir, '2.0'))
copy_tree(os.path.join(mono_etc_dir, '4.0'), os.path.join(target_mono_config_dir, '4.0'))
copy_tree(os.path.join(mono_etc_dir, '4.5'), os.path.join(target_mono_config_dir, '4.5'))
copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig'))
if os.path.isdir(os.path.join(mono_etc_dir, 'mconfig')):
copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig'))
for file in glob(os.path.join(mono_etc_dir, '*')):
if os.path.isfile(file):
copy(file, target_mono_config_dir)
def copy_mono_shared_libs(mono_root, target_mono_root_dir, platform):
def copy_mono_shared_libs(env, mono_root, target_mono_root_dir):
from shutil import copy
def copy_if_exists(src, dst):
if os.path.isfile(src):
copy(src, dst)
platform = env['platform']
if platform == 'windows':
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'), os.path.join(target_mono_bin_dir, 'MonoPosixHelper.dll'))
copy(os.path.join(mono_root, 'bin', 'MonoPosixHelper.dll'), target_mono_bin_dir)
else:
target_mono_lib_dir = os.path.join(target_mono_root_dir, 'lib')
target_mono_lib_dir = get_android_out_dir(env) if platform == 'android' else os.path.join(target_mono_root_dir, 'lib')
if not os.path.isdir(target_mono_lib_dir):
os.makedirs(target_mono_lib_dir)
if platform == 'osx':
copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.dylib'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.dylib'))
elif platform == 'x11':
copy(os.path.join(mono_root, 'lib', 'libmono-btls-shared.so'), os.path.join(target_mono_lib_dir, 'libmono-btls-shared.so'))
copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.so'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.so'))
# TODO: Make sure nothing is missing
copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.dylib'), target_mono_lib_dir)
elif platform == 'x11' or platform == 'android':
lib_file_names = [lib_name + '.so' for lib_name in [
'libmono-btls-shared', 'libmono-ee-interp', 'libmono-native', 'libMonoPosixHelper',
'libmono-profiler-aot', 'libmono-profiler-coverage', 'libmono-profiler-log', 'libMonoSupportW'
]]
for lib_file_name in lib_file_names:
copy_if_exists(os.path.join(mono_root, 'lib', lib_file_name), target_mono_lib_dir)
def configure_for_mono_version(env, mono_version):
if mono_version is None:
raise RuntimeError('Mono JIT compiler version not found')
if os.getenv('MONO_VERSION'):
mono_version = os.getenv('MONO_VERSION')
else:
raise RuntimeError("Mono JIT compiler version not found; specify one manually with the 'MONO_VERSION' environment variable")
print('Found Mono JIT compiler version: ' + str(mono_version))
if mono_version >= LooseVersion('5.12.0'):
env.Append(CPPFLAGS=['-DHAS_PENDING_EXCEPTIONS'])

View File

@ -0,0 +1,13 @@
diff --git a/mono/utils/mono-os-mutex.h b/mono/utils/mono-os-mutex.h
index e8039bf4094..ee39c0330b3 100644
--- a/mono/utils/mono-os-mutex.h
+++ b/mono/utils/mono-os-mutex.h
@@ -57,7 +57,7 @@ mono_os_mutex_init_type (mono_mutex_t *mutex, int type)
if (G_UNLIKELY (res != 0))
g_error ("%s: pthread_mutexattr_settype failed with \"%s\" (%d)", __func__, g_strerror (res), res);
-#ifdef PTHREAD_PRIO_INHERIT
+#if defined(PTHREAD_PRIO_INHERIT) && __ANDROID_API__ >= 28
/* use PTHREAD_PRIO_INHERIT if possible */
res = pthread_mutexattr_setprotocol (&attr, PTHREAD_PRIO_INHERIT);
if (G_UNLIKELY (res != 0 && res != ENOTSUP))

View File

@ -0,0 +1,70 @@
diff --git a/libgc/include/private/gcconfig.h b/libgc/include/private/gcconfig.h
index e2bdf13ac3e..f962200ba4e 100644
--- a/libgc/include/private/gcconfig.h
+++ b/libgc/include/private/gcconfig.h
@@ -2255,6 +2255,14 @@
# define GETPAGESIZE() getpagesize()
# endif
+#if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23) \
+ && ((defined(MIPS) && (CPP_WORDSZ == 32)) \
+ || defined(ARM32) || defined(I386) /* but not x32 */)
+ /* tkill() exists only on arm32/mips(32)/x86. */
+ /* NDK r11+ deprecates tkill() but keeps it for Mono clients. */
+# define USE_TKILL_ON_ANDROID
+#endif
+
# if defined(SUNOS5) || defined(DRSNX) || defined(UTS4)
/* OS has SVR4 generic features. Probably others also qualify. */
# define SVR4
diff --git a/libgc/pthread_stop_world.c b/libgc/pthread_stop_world.c
index f93ce26b562..4a49a6d578c 100644
--- a/libgc/pthread_stop_world.c
+++ b/libgc/pthread_stop_world.c
@@ -336,7 +336,7 @@ void GC_push_all_stacks()
pthread_t GC_stopping_thread;
int GC_stopping_pid;
-#ifdef HOST_ANDROID
+#ifdef USE_TKILL_ON_ANDROID
static
int android_thread_kill(pid_t tid, int sig)
{
diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c
index ad9b8823f8f..3542b32b540 100644
--- a/mono/metadata/threads.c
+++ b/mono/metadata/threads.c
@@ -77,8 +77,12 @@ mono_native_thread_join_handle (HANDLE thread_handle, gboolean close_handle);
#include <zircon/syscalls.h>
#endif
-#if defined(HOST_ANDROID) && !defined(TARGET_ARM64) && !defined(TARGET_AMD64)
-#define USE_TKILL_ON_ANDROID 1
+#if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23) \
+ && ((defined(MIPS) && (CPP_WORDSZ == 32)) \
+ || defined(ARM32) || defined(I386) /* but not x32 */)
+ /* tkill() exists only on arm32/mips(32)/x86. */
+ /* NDK r11+ deprecates tkill() but keeps it for Mono clients. */
+# define USE_TKILL_ON_ANDROID
#endif
#ifdef HOST_ANDROID
diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c
index 3e4bf93de5f..79c9f731fe7 100644
--- a/mono/utils/mono-threads-posix.c
+++ b/mono/utils/mono-threads-posix.c
@@ -31,8 +31,12 @@
#include <errno.h>
-#if defined(HOST_ANDROID) && !defined(TARGET_ARM64) && !defined(TARGET_AMD64)
-#define USE_TKILL_ON_ANDROID 1
+#if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23) \
+ && ((defined(MIPS) && (CPP_WORDSZ == 32)) \
+ || defined(ARM32) || defined(I386) /* but not x32 */)
+ /* tkill() exists only on arm32/mips(32)/x86. */
+ /* NDK r11+ deprecates tkill() but keeps it for Mono clients. */
+# define USE_TKILL_ON_ANDROID
#endif
#ifdef USE_TKILL_ON_ANDROID

View File

@ -380,7 +380,6 @@ public:
virtual bool supports_builtin_mode() const;
/* TODO? */ virtual int find_function(const String &p_function, const String &p_code) const { return -1; }
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
/* TODO? */ Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; }
virtual String _get_indentation() const;
/* TODO? */ virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const {}
/* TODO */ virtual void add_global_constant(const StringName &p_variable, const Variant &p_value) {}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
namespace GodotSharpTools.Editor
@ -62,7 +63,7 @@ namespace GodotSharpTools.Editor
{
// OSX export templates are contained in a zip, so we place
// our custom template inside it and let Godot do the rest.
return !featureSet.Contains("OSX");
return !featureSet.Any(f => new[] {"OSX", "Android"}.Contains(f));
}
[MethodImpl(MethodImplOptions.InternalCall)]

View File

@ -125,11 +125,21 @@ void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug
bool load_success = GDMono::get_singleton()->load_assembly_from(project_dll_name,
project_dll_src_path, &scripts_assembly, /* refonly: */ true);
ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name);
ERR_EXPLAIN("Cannot load assembly (refonly): " + project_dll_name);
ERR_FAIL_COND(!load_success);
Vector<String> search_dirs;
GDMonoAssembly::fill_search_dirs(search_dirs, build_config);
String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
String android_bcl_dir = templates_dir.plus_file("android-bcl");
String custom_lib_dir;
if (p_features.find("Android") && DirAccess::exists(android_bcl_dir)) {
custom_lib_dir = android_bcl_dir;
}
GDMonoAssembly::fill_search_dirs(search_dirs, build_config, custom_lib_dir);
Error depend_error = _get_assembly_dependencies(scripts_assembly, search_dirs, dependencies);
ERR_FAIL_COND(depend_error != OK);
}
@ -152,7 +162,7 @@ void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug
int i = 0;
for (const Set<String>::Element *E = p_features.front(); E; E = E->next()) {
MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get());
mono_array_set(features, MonoString *, i, boxed);
mono_array_setref(features, i, boxed);
i++;
}
@ -234,8 +244,10 @@ Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, c
r_dependencies.insert(ref_name, ref_assembly->get_path());
Error err = _get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies);
if (err != OK)
return err;
if (err != OK) {
ERR_EXPLAIN("Cannot load one of the dependencies for the assembly: " + ref_name);
ERR_FAIL_V(err);
}
}
return OK;

View File

@ -166,7 +166,7 @@ MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
int i = 0;
for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get().name);
mono_array_set(result, MonoString *, i, boxed);
mono_array_setref(result, i, boxed);
i++;
}

View File

@ -251,17 +251,19 @@ void GDMono::initialize() {
String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir();
#ifdef TOOLS_ENABLED
if (DirAccess::exists(bundled_assembly_rootdir) && DirAccess::exists(bundled_config_dir)) {
if (DirAccess::exists(bundled_assembly_rootdir)) {
assembly_rootdir = bundled_assembly_rootdir;
}
if (DirAccess::exists(bundled_config_dir)) {
config_dir = bundled_config_dir;
}
#ifdef WINDOWS_ENABLED
if (assembly_rootdir.empty() || 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);
ERR_PRINT("Cannot find Mono in the registry");
}
#endif // WINDOWS_ENABLED
@ -807,6 +809,8 @@ Error GDMono::_unload_scripts_domain() {
mono_gc_collect(mono_gc_max_generation());
GDMonoUtils::clear_godot_api_cache();
_domain_assemblies_cleanup(mono_domain_get_id(scripts_domain));
core_api_assembly = NULL;
@ -926,6 +930,7 @@ Error GDMono::reload_scripts_domain() {
Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) {
CRASH_COND(p_domain == NULL);
CRASH_COND(p_domain == SCRIPTS_DOMAIN); // Should use _unload_scripts_domain() instead
String domain_name = mono_domain_get_friendly_name(p_domain);
@ -1078,8 +1083,6 @@ GDMono::~GDMono() {
}
assemblies.clear();
GDMonoUtils::clear_cache();
print_verbose("Mono: Runtime cleanup...");
mono_jit_cleanup(root_domain);

View File

@ -46,11 +46,17 @@ bool GDMonoAssembly::in_preload = false;
Vector<String> GDMonoAssembly::search_dirs;
void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config) {
void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config, const String &p_custom_bcl_dir) {
const char *rootdir = mono_assembly_getrootdir();
if (rootdir) {
String framework_dir = String::utf8(rootdir).plus_file("mono").plus_file("4.5");
String framework_dir;
if (!p_custom_bcl_dir.empty()) {
framework_dir = p_custom_bcl_dir;
} else if (mono_assembly_getrootdir()) {
framework_dir = String::utf8(mono_assembly_getrootdir()).plus_file("mono").plus_file("4.5");
}
if (!framework_dir.empty()) {
r_search_dirs.push_back(framework_dir);
r_search_dirs.push_back(framework_dir.plus_file("Facades"));
}

View File

@ -122,7 +122,7 @@ public:
GDMonoClass *get_object_derived_class(const StringName &p_class);
static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String());
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);

View File

@ -1019,7 +1019,7 @@ MonoArray *PoolStringArray_to_mono_array(const PoolStringArray &p_array) {
for (int i = 0; i < p_array.size(); i++) {
MonoString *boxed = mono_string_from_godot(r[i]);
mono_array_set(ret, MonoString *, i, boxed);
mono_array_setref(ret, i, boxed);
}
return ret;

View File

@ -109,7 +109,7 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params,
for (int i = 0; i < params_count; i++) {
MonoObject *boxed_param = GDMonoMarshal::variant_to_mono_object(p_params[i], param_types[i]);
mono_array_set(params, MonoObject *, i, boxed_param);
mono_array_setref(params, i, boxed_param);
}
MonoException *exc = NULL;

View File

@ -142,7 +142,7 @@ bool GDMonoProperty::has_setter() {
void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) {
MonoMethod *prop_method = mono_property_get_set_method(mono_property);
MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), 1);
mono_array_set(params, MonoObject *, 0, p_value);
mono_array_setref(params, 0, p_value);
MonoException *exc = NULL;
GDMonoUtils::runtime_invoke_array(prop_method, p_object, params, &exc);
if (exc) {

View File

@ -50,6 +50,7 @@ MonoCache mono_cache;
#define CACHE_AND_CHECK(m_var, m_val) \
{ \
CRASH_COND(m_var != NULL); \
m_var = m_val; \
if (!m_var) { \
ERR_EXPLAIN("Mono Cache: Member " #m_var " is null"); \
@ -65,7 +66,9 @@ MonoCache mono_cache;
#define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val)
#define CACHE_PROPERTY_AND_CHECK(m_class, m_property, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.property_##m_class##_##m_property, m_val)
void MonoCache::clear_members() {
void MonoCache::clear_corlib_cache() {
corlib_cache_updated = false;
class_MonoObject = NULL;
class_bool = NULL;
@ -93,6 +96,11 @@ void MonoCache::clear_members() {
#endif
class_KeyNotFoundException = NULL;
}
void MonoCache::clear_godot_api_cache() {
godot_api_cache_updated = false;
rawclass_Dictionary = NULL;
@ -176,12 +184,6 @@ void MonoCache::clear_members() {
task_scheduler_handle = Ref<MonoGCHandle>();
}
void MonoCache::cleanup() {
corlib_cache_updated = false;
godot_api_cache_updated = false;
}
#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
#define GODOT_API_NS_CLAS(m_ns, m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(m_ns, #m_class))
@ -281,13 +283,10 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, (GenericIEnumerableIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, (GenericIDictionaryIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 2));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info, (GenericIDictionaryIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericArrayType, (MakeGenericArrayType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericArrayType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericDictionaryType, (MakeGenericDictionaryType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericDictionaryType", 2));
@ -310,11 +309,6 @@ void update_godot_api_cache() {
mono_cache.godot_api_cache_updated = true;
}
void clear_cache() {
mono_cache.cleanup();
mono_cache.clear_members();
}
MonoObject *unmanaged_get_managed(Object *unmanaged) {
if (!unmanaged)

View File

@ -218,14 +218,12 @@ struct MonoCache {
bool corlib_cache_updated;
bool godot_api_cache_updated;
void clear_members();
void cleanup();
void clear_corlib_cache();
void clear_godot_api_cache();
MonoCache() {
corlib_cache_updated = false;
godot_api_cache_updated = false;
clear_members();
clear_corlib_cache();
clear_godot_api_cache();
}
};
@ -233,7 +231,13 @@ extern MonoCache mono_cache;
void update_corlib_cache();
void update_godot_api_cache();
void clear_cache();
inline void clear_corlib_cache() {
mono_cache.clear_corlib_cache();
}
inline void clear_godot_api_cache() {
mono_cache.clear_godot_api_cache();
}
_FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash) {
p_hash ^= p_with_hash + 0x9e3779b9 + (p_hash << 6) + (p_hash >> 2);

View File

@ -95,7 +95,7 @@ Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_argc
for (int i = 0; i < signal_argc; i++) {
MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_args[i]);
mono_array_set(signal_args, MonoObject *, i, boxed);
mono_array_setref(signal_args, i, boxed);
}
MonoException *exc = NULL;