summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2019-06-03 18:06:07 +0200
committerGitHub <noreply@github.com>2019-06-03 18:06:07 +0200
commit42569f566f7750e355bf07f15008b54677043536 (patch)
tree1f896d45a14d5a7c777d45b02ad7ca780cc30cd7 /modules/mono
parent22583ec6a39bb56943c78c0ed9a094b28b666b75 (diff)
parent14df9e5cb2e9f2de4adf9b979e8ef33de37b80bd (diff)
Merge pull request #29359 from neikeq/android-mono
Android build and export for the mono module
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/build_scripts/godotsharptools_build.py35
-rw-r--r--modules/mono/build_scripts/mono_configure.py131
-rw-r--r--modules/mono/build_scripts/patches/fix-mono-android-pthread_mutexattr_setprotocol.diff13
-rw-r--r--modules/mono/build_scripts/patches/fix-mono-android-tkill.diff70
-rw-r--r--modules/mono/csharp_script.h1
-rw-r--r--modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs3
-rw-r--r--modules/mono/editor/godotsharp_export.cpp22
-rw-r--r--modules/mono/glue/base_object_glue.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp13
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_method.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_property.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp26
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h18
-rw-r--r--modules/mono/signal_awaiter_utils.cpp2
17 files changed, 237 insertions, 121 deletions
diff --git a/modules/mono/build_scripts/godotsharptools_build.py b/modules/mono/build_scripts/godotsharptools_build.py
index af3a5cb5c6..17f9a990af 100644
--- a/modules/mono/build_scripts/godotsharptools_build.py
+++ b/modules/mono/build_scripts/godotsharptools_build.py
@@ -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
-
- mono_root = ''
- bits = env['bits']
+ from . mono_reg_utils import find_mono_root_dir
- 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, {})
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index 4cfa2a5b93..2bce3ed376 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -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 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 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_root = mono_prefix
- 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 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'])
diff --git a/modules/mono/build_scripts/patches/fix-mono-android-pthread_mutexattr_setprotocol.diff b/modules/mono/build_scripts/patches/fix-mono-android-pthread_mutexattr_setprotocol.diff
new file mode 100644
index 0000000000..21cb1a0cf8
--- /dev/null
+++ b/modules/mono/build_scripts/patches/fix-mono-android-pthread_mutexattr_setprotocol.diff
@@ -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))
diff --git a/modules/mono/build_scripts/patches/fix-mono-android-tkill.diff b/modules/mono/build_scripts/patches/fix-mono-android-tkill.diff
new file mode 100644
index 0000000000..05f8dcadcc
--- /dev/null
+++ b/modules/mono/build_scripts/patches/fix-mono-android-tkill.diff
@@ -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
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 5525c0a121..4a1fb8e5ed 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -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) {}
diff --git a/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs
index e45dd2025b..44a43f0ddd 100644
--- a/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs
+++ b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs
@@ -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)]
diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp
index ae5b939b26..126178125f 100644
--- a/modules/mono/editor/godotsharp_export.cpp
+++ b/modules/mono/editor/godotsharp_export.cpp
@@ -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;
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 7385014a53..75b2dfce9a 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -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++;
}
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 19e49d29f9..7699e0d0cd 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -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);
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 8fec28b186..f1f0015ac9 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -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"));
}
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 32432af37d..39749dfc1d 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -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);
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index c462b8f71d..87157ed233 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -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;
diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp
index f290c6c8ac..968b316a3e 100644
--- a/modules/mono/mono_gd/gd_mono_method.cpp
+++ b/modules/mono/mono_gd/gd_mono_method.cpp
@@ -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;
diff --git a/modules/mono/mono_gd/gd_mono_property.cpp b/modules/mono/mono_gd/gd_mono_property.cpp
index 5842e26241..f1da00638f 100644
--- a/modules/mono/mono_gd/gd_mono_property.cpp
+++ b/modules/mono/mono_gd/gd_mono_property.cpp
@@ -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) {
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 413c8cba85..1b32f1126e 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -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)
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index ee239be959..00e1ffdd31 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -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);
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 5d37e8212f..0e1739b754 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -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;