2020-10-13 14:55:07 +02:00
|
|
|
#!/usr/bin/env python3
|
2019-11-10 04:58:04 +01:00
|
|
|
|
|
|
|
import os
|
|
|
|
import os.path
|
|
|
|
import runtime
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from options import *
|
|
|
|
from os_utils import *
|
|
|
|
from os.path import join as path_join
|
|
|
|
|
|
|
|
|
|
|
|
runtime_targets = ['runtime', 'runtime-threads', 'runtime-dynamic']
|
|
|
|
cross_targets = [] # ['cross'] # TODO
|
|
|
|
cross_mxe_targets = [] # ['cross-win'] # TODO
|
|
|
|
|
|
|
|
|
|
|
|
def is_cross(target) -> bool:
|
|
|
|
return target in cross_targets or is_cross_mxe(target)
|
|
|
|
|
|
|
|
|
|
|
|
def is_cross_mxe(target) -> bool:
|
|
|
|
return target in cross_mxe_targets
|
|
|
|
|
|
|
|
|
|
|
|
def setup_wasm_target_template(env: dict, opts: RuntimeOpts, target: str):
|
|
|
|
extra_target_envs = {
|
|
|
|
'runtime-threads': {
|
|
|
|
'wasm_runtime-threads_CFLAGS': ['-s', 'USE_PTHREADS=1', '-pthread'],
|
|
|
|
'wasm_runtime-threads_CXXFLAGS': ['-s', 'USE_PTHREADS=1', '-pthread']
|
|
|
|
},
|
|
|
|
'runtime-dynamic': {
|
|
|
|
'wasm_runtime-dynamic_CFLAGS': ['-s', 'WASM_OBJECT_FILES=0'],
|
|
|
|
'wasm_runtime-dynamic_CXXFLAGS': ['-s', 'WASM_OBJECT_FILES=0']
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if target in extra_target_envs:
|
|
|
|
env.update(extra_target_envs[target])
|
|
|
|
|
|
|
|
CFLAGS = ['-fexceptions']
|
|
|
|
CFLAGS += ['-Os', '-g'] if opts.release else ['-O0', '-ggdb3', '-fno-omit-frame-pointer']
|
|
|
|
CXXFLAGS = CFLAGS + ['-s', 'DISABLE_EXCEPTION_CATCHING=0']
|
|
|
|
|
|
|
|
CONFIGURE_FLAGS = [
|
|
|
|
'--disable-mcs-build',
|
|
|
|
'--disable-nls',
|
|
|
|
'--disable-boehm',
|
|
|
|
'--disable-btls',
|
|
|
|
'--with-lazy-gc-thread-creation=yes',
|
|
|
|
'--with-libgc=none',
|
|
|
|
'--disable-executables',
|
|
|
|
'--disable-support-build',
|
|
|
|
'--disable-visibility-hidden',
|
|
|
|
'--enable-maintainer-mode',
|
|
|
|
'--enable-minimal=ssa,com,jit,reflection_emit_save,portability,assembly_remapping,attach,verifier,full_messages,appdomains,security,sgen_marksweep_conc,sgen_split_nursery,sgen_gc_bridge,logging,remoting,shared_perfcounters,sgen_debug_helpers,soft_debug,interpreter,assert_messages,cleanup,mdb,gac',
|
|
|
|
'--host=wasm32',
|
|
|
|
'--enable-llvm-runtime',
|
|
|
|
'--enable-icall-export',
|
|
|
|
'--disable-icall-tables',
|
|
|
|
'--disable-crash-reporting',
|
|
|
|
'--with-bitcode=yes'
|
|
|
|
]
|
|
|
|
|
|
|
|
CONFIGURE_FLAGS += ['--enable-cxx'] if opts.enable_cxx else []
|
|
|
|
|
|
|
|
CONFIGURE_FLAGS += [
|
|
|
|
'--cache-file=%s/wasm-%s-%s.config.cache' % (opts.configure_dir, target, opts.configuration),
|
|
|
|
'--prefix=%s/wasm-%s-%s' % (opts.install_dir, target, opts.configuration),
|
2019-12-04 15:15:25 +01:00
|
|
|
'CFLAGS=%s %s' % (' '.join(CFLAGS), ' '.join(env.get('wasm_%s_CFLAGS' % target, ''))),
|
|
|
|
'CXXFLAGS=%s %s' % (' '.join(CXXFLAGS), ' '.join(env.get('wasm_%s_CXXFLAGS' % target, '')))
|
2019-11-10 04:58:04 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
CONFIGURE_FLAGS += env.get('wasm_%s_CONFIGURE_FLAGS' % target, [])
|
|
|
|
|
|
|
|
env['_wasm_%s_CONFIGURE_FLAGS' % target] = CONFIGURE_FLAGS
|
|
|
|
env['_wasm_%s_AC_VARS' % target] = ['ac_cv_func_shm_open_working_with_mmap=no']
|
|
|
|
|
|
|
|
|
|
|
|
def wasm_run_configure(env: dict, opts: RuntimeOpts, product: str, target: str, emsdk_root: str):
|
|
|
|
build_dir = path_join(opts.configure_dir, '%s-%s-%s' % (product, target, opts.configuration))
|
|
|
|
mkdir_p(build_dir)
|
|
|
|
|
|
|
|
def str_dict_val(val):
|
|
|
|
if isinstance(val, list):
|
|
|
|
return ' '.join(val) # Don't need to surround with quotes
|
|
|
|
return val
|
|
|
|
|
|
|
|
ac_vars = env['_%s_%s_AC_VARS' % (product, target)]
|
|
|
|
configure_flags = env['_%s_%s_CONFIGURE_FLAGS' % (product, target)]
|
|
|
|
|
|
|
|
configure = path_join(opts.mono_source_root, 'configure')
|
|
|
|
configure_args = ac_vars + configure_flags
|
|
|
|
|
|
|
|
configure_env = os.environ.copy()
|
|
|
|
|
|
|
|
target_extra_path = env.get('_%s-%s_PATH' % (product, target), '')
|
|
|
|
if target_extra_path:
|
|
|
|
configure_env['PATH'] += ':' + target_extra_path
|
|
|
|
|
|
|
|
configure_env['PATH'] = emsdk_root + ':' + configure_env['PATH']
|
|
|
|
|
|
|
|
run_command('emconfigure', args=[configure] + configure_args, cwd=build_dir, env=configure_env, name='configure')
|
|
|
|
|
|
|
|
|
|
|
|
def configure(opts: RuntimeOpts, product: str, target: str):
|
|
|
|
env = {}
|
|
|
|
|
|
|
|
if is_cross(target):
|
|
|
|
if is_cross_mxe(target):
|
|
|
|
raise RuntimeError('TODO')
|
|
|
|
else:
|
|
|
|
raise RuntimeError('TODO')
|
|
|
|
else:
|
|
|
|
setup_wasm_target_template(env, opts, target)
|
|
|
|
|
|
|
|
if not os.path.isfile(path_join(opts.mono_source_root, 'configure')):
|
|
|
|
runtime.run_autogen(opts)
|
|
|
|
|
|
|
|
wasm_run_configure(env, opts, product, target, get_emsdk_root())
|
|
|
|
|
|
|
|
|
|
|
|
def make(opts: RuntimeOpts, product: str, target: str):
|
|
|
|
env = {}
|
|
|
|
|
|
|
|
emsdk_root = get_emsdk_root()
|
|
|
|
|
|
|
|
build_dir = path_join(opts.configure_dir, '%s-%s-%s' % (product, target, opts.configuration))
|
|
|
|
install_dir = path_join(opts.install_dir, '%s-%s-%s' % (product, target, opts.configuration))
|
|
|
|
|
2020-04-06 11:01:36 +02:00
|
|
|
make_args = make_default_args(opts)
|
|
|
|
make_args += ['-C', build_dir]
|
2019-11-10 04:58:04 +01:00
|
|
|
|
|
|
|
make_env = os.environ.copy()
|
|
|
|
make_env['PATH'] = emsdk_root + ':' + make_env['PATH']
|
|
|
|
|
|
|
|
run_command('emmake', args=['make'] + make_args, env=make_env, name='make')
|
|
|
|
|
|
|
|
run_command('make', args=['-C', '%s/mono' % build_dir, 'install'], name='make install mono')
|
2019-11-13 21:09:19 +01:00
|
|
|
run_command('make', args=['-C', '%s/data' % build_dir, 'install'], name='make install data')
|
2019-11-10 04:58:04 +01:00
|
|
|
|
|
|
|
# Copy support headers
|
|
|
|
|
|
|
|
from shutil import copy
|
|
|
|
|
|
|
|
headers = ['crc32.h', 'deflate.h', 'inffast.h', 'inffixed.h', 'inflate.h', 'inftrees.h', 'trees.h', 'zconf.h', 'zlib.h', 'zutil.h']
|
2019-11-14 15:59:49 +01:00
|
|
|
dst_zlib_dir = '%s/include/support' % install_dir
|
2019-11-10 04:58:04 +01:00
|
|
|
|
2019-11-14 15:59:49 +01:00
|
|
|
src_zlib_dir = None
|
|
|
|
src_zlib_dir_hints = ['%s/mono/zlib' % opts.mono_source_root, '%s/support' % opts.mono_source_root]
|
|
|
|
|
|
|
|
for src_zlib_dir_hint in src_zlib_dir_hints:
|
|
|
|
if os.path.isfile(path_join(src_zlib_dir_hint, 'zlib.h')):
|
|
|
|
src_zlib_dir = src_zlib_dir_hint
|
|
|
|
break
|
|
|
|
|
|
|
|
if src_zlib_dir is None:
|
|
|
|
raise BuildError('Cannot find the support zlib headers in the Mono source tree. Tried the following locations: ' + str(src_zlib_dir_hints))
|
|
|
|
|
|
|
|
mkdir_p(dst_zlib_dir)
|
2019-11-10 04:58:04 +01:00
|
|
|
|
|
|
|
for header in headers:
|
2019-11-14 15:59:49 +01:00
|
|
|
copy(path_join(src_zlib_dir, header), dst_zlib_dir)
|
2019-11-10 04:58:04 +01:00
|
|
|
|
|
|
|
# Copy wasm src files
|
|
|
|
|
|
|
|
wasm_src_files = [
|
|
|
|
'driver.c',
|
|
|
|
'corebindings.c',
|
2019-12-04 15:15:25 +01:00
|
|
|
'zlib-helper.c',
|
2019-11-10 04:58:04 +01:00
|
|
|
'pinvoke-tables-default.h',
|
|
|
|
'library_mono.js',
|
|
|
|
'binding_support.js',
|
|
|
|
'dotnet_support.js'
|
|
|
|
]
|
|
|
|
|
|
|
|
dst_wasm_src_dir = path_join(install_dir, 'src')
|
|
|
|
|
|
|
|
mkdir_p(dst_wasm_src_dir)
|
|
|
|
|
2019-12-04 15:15:25 +01:00
|
|
|
src_dir_hints = [
|
|
|
|
'%s/sdks/wasm/src' % opts.mono_source_root,
|
|
|
|
'%s/sdks/wasm/support' % opts.mono_source_root,
|
|
|
|
'%s/sdks/wasm' % opts.mono_source_root
|
|
|
|
]
|
2019-11-14 15:59:49 +01:00
|
|
|
|
2019-12-04 15:15:25 +01:00
|
|
|
def dir_with_file(dirs, file):
|
|
|
|
return (d for d in dirs if os.path.isfile(path_join(d, file)))
|
2019-11-14 15:59:49 +01:00
|
|
|
|
2019-11-10 04:58:04 +01:00
|
|
|
for wasm_src_file in wasm_src_files:
|
2019-12-04 15:15:25 +01:00
|
|
|
src_dir = next(dir_with_file(src_dir_hints, wasm_src_file), '')
|
|
|
|
if not src_dir:
|
|
|
|
raise BuildError('File \'%s\' not found. Probed locations: %s' % (wasm_src_file, str(src_dir_hints)))
|
|
|
|
copy(path_join(src_dir, wasm_src_file), dst_wasm_src_dir)
|
2019-11-14 15:59:49 +01:00
|
|
|
|
|
|
|
# Older versions didn't have .NET Core support
|
2019-12-04 15:15:25 +01:00
|
|
|
src_dir = next(dir_with_file(src_dir_hints, 'pinvoke-tables-default-netcore.h'), '')
|
|
|
|
if src_dir:
|
|
|
|
copy(path_join(src_dir, 'pinvoke-tables-default-netcore.h'), dst_wasm_src_dir)
|
2019-11-10 04:58:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
def clean(opts: RuntimeOpts, product: str, target: str):
|
|
|
|
rm_rf(
|
|
|
|
path_join(opts.configure_dir, '%s-%s-%s' % (product, target, opts.configuration)),
|
|
|
|
path_join(opts.configure_dir, '%s-%s-%s.config.cache' % (product, target, opts.configuration)),
|
|
|
|
path_join(opts.install_dir, '%s-%s-%s' % (product, target, opts.configuration))
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def main(raw_args):
|
|
|
|
import cmd_utils
|
|
|
|
from collections import OrderedDict
|
|
|
|
from typing import Callable
|
|
|
|
|
|
|
|
target_shortcuts = {'all-runtime': runtime_targets}
|
|
|
|
|
|
|
|
target_values = runtime_targets + cross_targets + cross_mxe_targets + list(target_shortcuts)
|
|
|
|
|
|
|
|
actions = OrderedDict()
|
|
|
|
actions['configure'] = configure
|
|
|
|
actions['make'] = make
|
|
|
|
actions['clean'] = clean
|
|
|
|
|
|
|
|
parser = cmd_utils.build_arg_parser(description='Builds the Mono runtime for WebAssembly')
|
|
|
|
|
|
|
|
emsdk_root_default = os.environ.get('EMSDK_ROOT', default='')
|
|
|
|
|
|
|
|
default_help = 'default: %(default)s'
|
|
|
|
|
|
|
|
parser.add_argument('action', choices=['configure', 'make', 'clean'])
|
|
|
|
parser.add_argument('--target', choices=target_values, action='append', required=True)
|
|
|
|
|
|
|
|
cmd_utils.add_runtime_arguments(parser, default_help)
|
|
|
|
|
|
|
|
args = parser.parse_args(raw_args)
|
|
|
|
|
|
|
|
input_action = args.action
|
|
|
|
input_targets = args.target
|
|
|
|
|
|
|
|
opts = runtime_opts_from_args(args)
|
|
|
|
|
|
|
|
if not os.path.isdir(opts.mono_source_root):
|
|
|
|
print('Mono sources directory not found: ' + opts.mono_source_root)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
targets = cmd_utils.expand_input_targets(input_targets, target_shortcuts)
|
|
|
|
action = actions[input_action]
|
|
|
|
|
|
|
|
try:
|
|
|
|
for target in targets:
|
|
|
|
action(opts, 'wasm', target)
|
|
|
|
except BuildError as e:
|
|
|
|
sys.exit(e.message)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
from sys import argv
|
|
|
|
main(argv[1:])
|