mirror of
https://github.com/godotengine/godot.git
synced 2024-11-27 09:16:35 +08:00
Merge pull request #29359 from neikeq/android-mono
Android build and export for the mono module
This commit is contained in:
commit
42569f566f
@ -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, {})
|
||||
|
@ -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'])
|
||||
|
@ -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))
|
@ -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
|
@ -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) {}
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
@ -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++;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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"));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user