1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

Android build and export for the mono module

This commit is contained in:
Ignacio Etcheverry
2019-05-20 18:34:35 +02:00
parent 22583ec6a3
commit 14df9e5cb2
17 changed files with 238 additions and 122 deletions

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'])