Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2018-09-26 12:29:00 +0300
committerGitHub <noreply@github.com>2018-09-26 12:29:00 +0300
commit352639f75a389150a1562ebf72a7d46f4acc475e (patch)
tree19e9dbd418fe5ce27b7afadb2247d9eed5d0129c
parent7e4159b5682f28cd4556b850b9038eb9ab66e868 (diff)
[wasm] AOT fixes (#10706)
* [wasm] Fix linker changes. * Revert "[wasm] Enable the mini test suite under AOT. (#10670)" This reverts commit 9cb832ff2a3c09058b8c220bbd021f1177c2b7aa. Revert this, it doesn't work yet. * [wasm] Run AOT tests on CI. * Fix the CI label. * [wasm] Disable the aot test on CI, it doesn't yet run on linux. * [wasm] Fix the computation of code_start/code_end for wasm. * [llvm] Avoid passing a dummy extra args to wrappers which don't need it. * [wasm] Enable gshared. * [llvm] Fix the build. * [llvm] Avoid passing a dummy arg to string:memcpy/bzero. * [wasm] Enable exception catching. * [wasm] Enable explicit division by zero checks. * [wasm] Patch emscripten with the patch from https://github.com/kripken/emscripten/pull/7182. * [wasm] Use '.' instead of source in the ninja build scripts since they might be ran with sh/dash instead of bash. * [wasm] Reenable check-aot on CI. * [wasm] Run emcc using bash -c since the emsdk_env.sh scripts contains bash-ishms. * [wasm] Don't error out if the emscripten patch is already applied. * [wasm] Fix do-aot-sample. * [wasm] Disable AOT test on CI, it still doesn't work. * [llvm] Add support for OP_RCNEQ. * [jit] Make some tests in builtin-types.cs static. * [wasm] Fix the return value of mono_wasm_exec_regression (). * [wasm] Make aot-sample uses mini_tests.dll.
-rw-r--r--mono/mini/aot-runtime.c29
-rw-r--r--mono/mini/builtin-types.cs6
-rw-r--r--mono/mini/mini-codegen.c1
-rw-r--r--mono/mini/mini-llvm.c57
-rw-r--r--mono/mini/mini-wasm.h2
-rwxr-xr-xscripts/ci/run-jenkins.sh1
-rw-r--r--sdks/builds/emsdk-eh.diff19
-rw-r--r--sdks/builds/wasm.mk1
-rw-r--r--sdks/wasm/Makefile22
-rw-r--r--sdks/wasm/aot-driver.js126
-rw-r--r--sdks/wasm/driver.c2
-rw-r--r--sdks/wasm/packager.cs16
12 files changed, 252 insertions, 30 deletions
diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c
index 0a1bd8e8d73..3c31eae4a2d 100644
--- a/mono/mini/aot-runtime.c
+++ b/mono/mini/aot-runtime.c
@@ -2724,11 +2724,36 @@ compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **c
if (amodule->info.llvm_get_method) {
gpointer (*get_method) (int) = (gpointer (*)(int))amodule->info.llvm_get_method;
+#ifdef HOST_WASM
+ gsize min = 1 << 30, max = 0;
+ gsize prev = 0;
+
+ // FIXME: This depends on emscripten allocating ftnptr ids sequentially
+ for (int i = 0; i < amodule->info.nmethods; ++i) {
+ void *addr = NULL;
+
+ addr = get_method (i);
+ gsize val = (gsize)addr;
+ if (val) {
+ g_assert (val > prev);
+ if (val < min)
+ min = val;
+ else if (val > max)
+ max = val;
+ prev = val;
+ }
+ }
+ if (max) {
+ *code_start = (guint8*)min;
+ *code_end = (guint8*)(max + 1);
+ } else {
+ *code_start = NULL;
+ *code_end = NULL;
+ }
+#else
*code_start = (guint8 *)get_method (-1);
*code_end = (guint8 *)get_method (-2);
- //WASM doesn't support this
-#ifndef HOST_WASM
g_assert (*code_end > *code_start);
#endif
return;
diff --git a/mono/mini/builtin-types.cs b/mono/mini/builtin-types.cs
index 69b328de8c0..af2b249f72b 100644
--- a/mono/mini/builtin-types.cs
+++ b/mono/mini/builtin-types.cs
@@ -259,7 +259,7 @@ public class BuiltinTests {
return 0;
}
- public int test_0_nint_unboxed_member_calls ()
+ static int test_0_nint_unboxed_member_calls ()
{
var x = (nint)10;
#if FALSE
@@ -521,7 +521,7 @@ public class BuiltinTests {
return 0;
}
- public int test_0_nuint_unboxed_member_calls ()
+ static int test_0_nuint_unboxed_member_calls ()
{
var x = (nuint)10;
#if FALSE
@@ -780,7 +780,7 @@ public class BuiltinTests {
return 0;
}
- public int test_0_nfloat_unboxed_member_calls ()
+ static int test_0_nfloat_unboxed_member_calls ()
{
var x = (nfloat)10f;
#if FALSE
diff --git a/mono/mini/mini-codegen.c b/mono/mini/mini-codegen.c
index 096c0979eeb..c8053799ec7 100644
--- a/mono/mini/mini-codegen.c
+++ b/mono/mini/mini-codegen.c
@@ -2346,6 +2346,7 @@ mono_opcode_to_cond (int opcode)
case OP_CMOV_LEQ:
return CMP_EQ;
case OP_FCNEQ:
+ case OP_RCNEQ:
case OP_ICNEQ:
case OP_IBNE_UN:
case OP_LBNE_UN:
diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c
index 3c8f840328b..f97c96d961e 100644
--- a/mono/mini/mini-llvm.c
+++ b/mono/mini/mini-llvm.c
@@ -3193,6 +3193,58 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
ctx->builder = old_builder;
}
+static gboolean
+needs_extra_arg (EmitContext *ctx, MonoMethod *method)
+{
+ WrapperInfo *info = NULL;
+
+ /*
+ * When targeting wasm, the caller and callee signature has to match exactly. This means
+ * that every method which can be called indirectly need an extra arg since the caller
+ * will call it through an ftnptr and will pass an extra arg.
+ */
+ if (!ctx->cfg->llvm_only || !ctx->emit_dummy_arg)
+ return FALSE;
+ if (method->wrapper_type)
+ info = mono_marshal_get_wrapper_info (method);
+
+ switch (method->wrapper_type) {
+ case MONO_WRAPPER_UNKNOWN:
+ if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG)
+ /* Already have an explicit extra arg */
+ return FALSE;
+ break;
+ case MONO_WRAPPER_MANAGED_TO_NATIVE:
+ if (strstr (method->name, "icall_wrapper"))
+ /* These are JIT icall wrappers which are only called from JITted code directly */
+ return FALSE;
+ /* Normal icalls can be virtual methods which need an extra arg */
+ break;
+ case MONO_WRAPPER_RUNTIME_INVOKE:
+ case MONO_WRAPPER_ALLOC:
+ case MONO_WRAPPER_CASTCLASS:
+ case MONO_WRAPPER_WRITE_BARRIER:
+ return FALSE;
+ case MONO_WRAPPER_STELEMREF:
+ if (info->subtype != WRAPPER_SUBTYPE_VIRTUAL_STELEMREF)
+ return FALSE;
+ break;
+ case MONO_WRAPPER_MANAGED_TO_MANAGED:
+ if (info->subtype == WRAPPER_SUBTYPE_STRING_CTOR)
+ return FALSE;
+ break;
+ default:
+ break;
+ }
+ if (method->string_ctor)
+ return FALSE;
+
+ /* These are called from gsharedvt code with an indirect call which doesn't pass an extra arg */
+ if (method->klass == mono_defaults.string_class && (strstr (method->name, "memcpy") || strstr (method->name, "bzero")))
+ return FALSE;
+ return TRUE;
+}
+
static void
process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, MonoInst *ins)
{
@@ -3227,7 +3279,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
cinfo->rgctx_arg = TRUE;
if (call->imt_arg_reg)
cinfo->imt_arg = TRUE;
- if (cfg->llvm_only && ctx->emit_dummy_arg && call->method && !call->method->wrapper_type)
+ if (call->method && needs_extra_arg (ctx, call->method))
cinfo->dummy_arg = TRUE;
vretaddr = (cinfo->ret.storage == LLVMArgVtypeRetAddr || cinfo->ret.storage == LLVMArgVtypeByRef || cinfo->ret.storage == LLVMArgGsharedvtFixed || cinfo->ret.storage == LLVMArgGsharedvtVariable || cinfo->ret.storage == LLVMArgGsharedvtFixedVtype);
@@ -4660,6 +4712,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
break;
}
case OP_RCEQ:
+ case OP_RCNEQ:
case OP_RCLT:
case OP_RCLT_UN:
case OP_RCGT:
@@ -7145,7 +7198,7 @@ emit_method_inner (EmitContext *ctx)
if (cfg->rgctx_var)
linfo->rgctx_arg = TRUE;
- else if (ctx->emit_dummy_arg && cfg->llvm_only && !cfg->method->wrapper_type)
+ else if (needs_extra_arg (ctx, cfg->method))
linfo->dummy_arg = TRUE;
ctx->method_type = method_type = sig_to_llvm_sig_full (ctx, sig, linfo);
if (!ctx_ok (ctx))
diff --git a/mono/mini/mini-wasm.h b/mono/mini/mini-wasm.h
index 7e500b3155e..b5c9e1c979e 100644
--- a/mono/mini/mini-wasm.h
+++ b/mono/mini/mini-wasm.h
@@ -19,8 +19,10 @@
#define MONO_ARCH_AOT_SUPPORTED 1
#define MONO_ARCH_LLVM_SUPPORTED 1
+#define MONO_ARCH_GSHARED_SUPPORTED 1
#define MONO_ARCH_GSHAREDVT_SUPPORTED 1
#define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
+#define MONO_ARCH_NEED_DIV_CHECK 1
#define MONO_ARCH_EMULATE_FREM 1
#define MONO_ARCH_FLOAT32_SUPPORTED 1
diff --git a/scripts/ci/run-jenkins.sh b/scripts/ci/run-jenkins.sh
index 3fd9c212dee..6323603cbaa 100755
--- a/scripts/ci/run-jenkins.sh
+++ b/scripts/ci/run-jenkins.sh
@@ -195,6 +195,7 @@ if [[ ${CI_TAGS} == *'webassembly'* ]];
${TESTCMD} --label=v8-system-core --timeout=60m make -C sdks/wasm run-v8-system-core
${TESTCMD} --label=sm-system-core --timeout=60m make -C sdks/wasm run-sm-system-core
${TESTCMD} --label=jsc-system-core --timeout=60m make -C sdks/wasm run-jsc-system-core
+ #${TESTCMD} --label=check-aot --timeout=60m make -C sdks/wasm check-aot
${TESTCMD} --label=package --timeout=60m make -C sdks/wasm package
exit 0
fi
diff --git a/sdks/builds/emsdk-eh.diff b/sdks/builds/emsdk-eh.diff
new file mode 100644
index 00000000000..67da70e2482
--- /dev/null
+++ b/sdks/builds/emsdk-eh.diff
@@ -0,0 +1,19 @@
+commit 09c043e560b69c5ba803f0b35eea75fb8f1ee85e
+Author: Zoltan Varga <vargaz@gmail.com>
+Date: Mon Sep 24 21:54:47 2018 +0200
+
+ Add '___cxa_is_pointer_type', '___cxa_can_catch' to the list of exported functions when exception catching is enabled.
+
+diff --git a/emcc.py b/emcc.py
+index bb2889fdb..65c71a174 100755
+--- a/emcc.py
++++ b/emcc.py
+@@ -1134,6 +1134,8 @@ There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR P
+ if shared.Settings.DEMANGLE_SUPPORT:
+ shared.Settings.EXPORTED_FUNCTIONS += ['___cxa_demangle']
+ forced_stdlibs += ['libcxxabi']
++ if shared.Settings.DISABLE_EXCEPTION_CATCHING != 1:
++ shared.Settings.EXPORTED_FUNCTIONS += ['___cxa_is_pointer_type', '___cxa_can_catch']
+
+ if not shared.Settings.ONLY_MY_CODE:
+ if type(shared.Settings.EXPORTED_FUNCTIONS) in (list, tuple):
diff --git a/sdks/builds/wasm.mk b/sdks/builds/wasm.mk
index 788e5192dc0..2814bece9c5 100644
--- a/sdks/builds/wasm.mk
+++ b/sdks/builds/wasm.mk
@@ -32,6 +32,7 @@ $(TOP)/sdks/builds/toolchains/emsdk:
git clone https://github.com/juj/emsdk.git $(EMSCRIPTEN_SDK_DIR)
cd $(TOP)/sdks/builds/toolchains/emsdk && ./emsdk install sdk-$(EMSCRIPTEN_VERSION)-64bit
cd $(TOP)/sdks/builds/toolchains/emsdk && ./emsdk activate --embedded sdk-$(EMSCRIPTEN_VERSION)-64bit
+ -cd $(TOP)/sdks/builds/toolchains/emsdk/emscripten/$(EMSCRIPTEN_VERSION) && patch -p1 < $(TOP)/sdks/builds/emsdk-eh.diff
.stamp-wasm-toolchain: | $(TOP)/sdks/builds/toolchains/emsdk
touch $@
diff --git a/sdks/wasm/Makefile b/sdks/wasm/Makefile
index 167f654ebf2..f64526db54e 100644
--- a/sdks/wasm/Makefile
+++ b/sdks/wasm/Makefile
@@ -142,26 +142,12 @@ TEST_ASSEMBLIES = $(WASM_BCL_DIR)/nunitlite.dll $(WASM_BCL_DIR)/tests/wasm_corli
ninja -v -C obj/test-suite
touch $@
-MINI_BASIC_TEST_FILES= \
- basic-calls.cs \
- basic-float.cs \
- basic-long.cs \
- basic-math.cs \
- basic.cs \
- objects.cs
-
-MINI_BASIC_TEST_SOURCES= $(patsubst %,$(MINI_PATH)/%,$(MINI_BASIC_TEST_FILES))
-
-mini_tests_basic.dll: $(MINI_BASIC_TEST_SOURCES)
- $(CSC) $(CSC_FLAGS) /unsafe -target:library -out:$@ -define:__MOBILE__,ARCH_32,NO_BITCODE /r:$(WASM_BCL_DIR)/mscorlib.dll $(MINI_BASIC_TEST_SOURCES)
-
-
-aot-sample: $(DRIVER_CONF)/.stamp-build packager.exe mini_tests_basic.dll main.exe runtime.g.js
- mono packager.exe --emscripten-sdkdir=$(EMSCRIPTEN_SDKDIR) --mono-sdkdir=$(PWD)/../out -appdir=bin/aot-sample --nobinding --builddir=obj/aot-sample --aot --template=runtime-tests.g.js mini_tests_basic.dll
+aot-sample: $(DRIVER_CONF)/.stamp-build packager.exe mini_tests.dll main.exe runtime.g.js
+ mono packager.exe --emscripten-sdkdir=$(EMSCRIPTEN_SDKDIR) --mono-sdkdir=$(PWD)/../out -appdir=bin/aot-sample --nobinding --builddir=obj/aot-sample --aot --template=runtime-tests.g.js mini_tests.dll
ninja -v -C obj/aot-sample
do-aot-sample: aot-sample
- (cd bin/aot-sample && $(SM) runtime.js mini)
+ (cd bin/aot-sample && $(SM) runtime.js --regression mini_tests.dll)
build-debug-sample: .stamp-build-debug-sample
@@ -248,3 +234,5 @@ serve:
canary:
/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --remote-debugging-port=9222
+
+check-aot: do-aot-sample
diff --git a/sdks/wasm/aot-driver.js b/sdks/wasm/aot-driver.js
new file mode 100644
index 00000000000..8f0385f083f
--- /dev/null
+++ b/sdks/wasm/aot-driver.js
@@ -0,0 +1,126 @@
+//glue code to deal with the differences between ch, d8, jsc and sm.
+if (print == undefined)
+ print = console.log;
+
+
+if (console != undefined) {
+ var has_console_warn = false;
+ try {
+ if (console.warn != undefined)
+ has_console_warn = true;
+ } catch(e) {}
+
+ if (!has_console_warn)
+ console.warn = console.log;
+}
+
+fail_exec = function(reason) {
+ print (reason);
+ throw "FAIL";
+}
+
+try {
+ arguments = WScript.Arguments;
+ load = WScript.LoadScriptFile;
+ read = WScript.LoadBinaryFile;
+ fail_exec = function(reason) {
+ print (reason);
+ WScript.Quit(1);
+ }
+} catch(e) {}
+
+try {
+ if (scriptArgs !== undefined)
+ arguments = scriptArgs;
+} catch(e) {}
+
+
+// load("runtime.js")
+
+var App = {
+ init: function () { print ("runtime init finished"); }
+};
+
+function ResolveEagerPromise(value) {
+ this.then = function(cb) {
+ var res = cb (value);
+ return new ResolveEagerPromise(res);
+ }
+}
+
+var Module = {
+ onRuntimeInitialized: function () {
+ print("initing the runtime");
+ MONO.mono_load_runtime_and_bcl (
+ "managed",
+ "managed",
+ 0,
+ [ "mscorlib.dll", "mini_tests_basic.dll", ],
+ function () { App.init (); },
+ function (file) {
+ // print("loading " + file)
+ return new ResolveEagerPromise ({
+ ok: true,
+ url: file,
+ arrayBuffer: function() { return read (file, 'binary') }
+ })
+ });
+ },
+
+ print: function(x) { print ("WASM: " + x) },
+ printErr: function(x) { print ("WASM-ERR: " + x) },
+
+ totalDependencies: 0,
+ monitorRunDependencies: function(left) {
+ this.totalDependencies = Math.max(this.totalDependencies, left);
+ print("STATUS: "+ (left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.'));
+ },
+
+ instantiateWasm: function (env, receiveInstance) {
+ //merge Module's env with emcc's env
+ env.env = Object.assign({}, env.env, this.env);
+ var module = new WebAssembly.Module (read ('mono.wasm', 'binary'))
+ this.wasm_instance = new WebAssembly.Instance (module, env);
+ this.em_cb = receiveInstance;
+ return this
+ },
+
+ finish_loading: function () {
+ this.em_cb (this.wasm_instance);
+ },
+
+ env: {
+ },
+
+};
+
+
+load("mono.js")
+Module.finish_loading ();
+
+function not_null(value) {
+ if (!value)
+ throw "error";
+ return value;
+}
+
+var assembly_load = Module.cwrap ('mono_wasm_assembly_load', 'number', ['string'])
+var find_class = Module.cwrap ('mono_wasm_assembly_find_class', 'number', ['number', 'string', 'string'])
+var find_method = Module.cwrap ('mono_wasm_assembly_find_method', 'number', ['number', 'string', 'number'])
+var mono_runtime_invoke = Module.cwrap ('mono_wasm_invoke_method', 'number', ['number', 'number', 'number', 'number']);
+var mono_unbox_int = Module.cwrap ('mono_unbox_int', 'number', ['number']);
+const IGNORE_PARAM_COUNT = -1;
+
+var test_suite = not_null (assembly_load("mini_tests_basic"))
+var basic_tests = not_null (find_class (test_suite, "", "BasicTests"))
+var test_0_return = not_null (find_method (basic_tests, "test_0_return", IGNORE_PARAM_COUNT))
+
+var eh_throw = Module._malloc (4);
+Module.setValue (eh_throw, 0, "i32");
+var res = mono_unbox_int (mono_runtime_invoke (test_0_return, 0, 0, eh_throw));
+var eh_res = Module.getValue (eh_throw, "i32");
+print ("res is " + res + " eh is " + eh_res);
+
+
+
+
diff --git a/sdks/wasm/driver.c b/sdks/wasm/driver.c
index 5a5b127d20f..e86e3d34846 100644
--- a/sdks/wasm/driver.c
+++ b/sdks/wasm/driver.c
@@ -592,5 +592,5 @@ mono_wasm_array_to_heap (MonoArray *src, char *dest)
EMSCRIPTEN_KEEPALIVE int
mono_wasm_exec_regression (int verbose_level, char *image)
{
- return mono_regression_test_step (verbose_level, image, NULL);
+ return mono_regression_test_step (verbose_level, image, NULL) ? 0 : 1;
}
diff --git a/sdks/wasm/packager.cs b/sdks/wasm/packager.cs
index ab061f7ae26..41fc6c1c6c6 100644
--- a/sdks/wasm/packager.cs
+++ b/sdks/wasm/packager.cs
@@ -258,6 +258,9 @@ class Driver {
if (vfs_prefix.EndsWith ("/"))
vfs_prefix = vfs_prefix.Substring (0, vfs_prefix.Length - 1);
+ var dontlink_assemblies = new Dictionary<string, bool> ();
+ dontlink_assemblies [BINDINGS_ASM_NAME] = true;
+
var template = File.ReadAllText (Path.Combine (tool_prefix, runtimeTemplate));
var file_list_str = string.Join (",", file_list.Select (f => $"\"{Path.GetFileName (f)}\""));
@@ -329,7 +332,7 @@ class Driver {
ninja.WriteLine ("cross = $mono_sdkdir/wasm-cross/bin/wasm32-mono-sgen");
ninja.WriteLine ("emcc = source $emscripten_sdkdir/emsdk_env.sh && emcc");
// -s ASSERTIONS=2 is very slow
- ninja.WriteLine ("emcc_flags = -Os -g -s ASSERTIONS=1 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN=1 -s \"BINARYEN_TRAP_MODE='clamp'\" -s TOTAL_MEMORY=134217728 -s ALIASING_FUNCTION_POINTERS=0 -s NO_EXIT_RUNTIME=1 -s \"EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'FS_createPath', 'FS_createDataFile', 'cwrap', 'setValue', 'getValue', 'UTF8ToString']\"");
+ ninja.WriteLine ("emcc_flags = -Os -g -s DISABLE_EXCEPTION_CATCHING=0 -s ASSERTIONS=1 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN=1 -s \"BINARYEN_TRAP_MODE=\'clamp\'\" -s TOTAL_MEMORY=134217728 -s ALIASING_FUNCTION_POINTERS=0 -s NO_EXIT_RUNTIME=1 -s \"EXTRA_EXPORTED_RUNTIME_METHODS=[\'ccall\', \'FS_createPath\', \'FS_createDataFile\', \'cwrap\', \'setValue\', \'getValue\', \'UTF8ToString\']\"");
// Rules
ninja.WriteLine ("rule aot");
@@ -341,13 +344,14 @@ class Driver {
ninja.WriteLine (" command = if cmp -s $in $out ; then : ; else cp $in $out ; fi");
ninja.WriteLine (" restat = true");
ninja.WriteLine ("rule emcc");
- ninja.WriteLine (" command = $emcc $emcc_flags $flags -c -o $out $in");
+ ninja.WriteLine (" command = bash -c '$emcc $emcc_flags $flags -c -o $out $in'");
ninja.WriteLine (" description = [EMCC] $in -> $out");
ninja.WriteLine ("rule emcc-link");
- ninja.WriteLine (" command = $emcc $emcc_flags -o $out --js-library $tool_prefix/library_mono.js --js-library $tool_prefix/binding_support.js --js-library $tool_prefix/dotnet_support.js $in");
+ ninja.WriteLine (" command = bash -c '$emcc $emcc_flags -o $out --js-library $tool_prefix/library_mono.js --js-library $tool_prefix/binding_support.js --js-library $tool_prefix/dotnet_support.js $in'");
ninja.WriteLine (" description = [EMCC-LINK] $in -> $out");
ninja.WriteLine ("rule linker");
- ninja.WriteLine (" command = mono $bcl_dir/monolinker.exe -out $builddir/linker-out $linker_args");
+
+ ninja.WriteLine (" command = mono $bcl_dir/monolinker.exe -out $builddir/linker-out -l none $linker_args; for f in $out; do if test ! -f $$f; then echo > empty.cs; csc /out:$$f /target:library empty.cs; fi; done");
ninja.WriteLine (" description = [IL-LINK]");
// Targets
@@ -379,7 +383,6 @@ class Driver {
var filename_noext = Path.GetFileNameWithoutExtension (filename);
var source_file_path = Path.GetFullPath (assembly);
- ninja.WriteLine ($"build $builddir/{filename}: cpifdiff {source_file_path}");
string infile = "";
if (enable_linker) {
@@ -416,6 +419,9 @@ class Driver {
string filename = Path.GetFileName (assembly);
linker_args += $"-a linker-in/{filename} ";
}
+ foreach (var assembly in dontlink_assemblies.Keys) {
+ linker_args += $"-p copy {assembly} ";
+ }
linker_args += " -d $bcl_dir -c link";
ninja.WriteLine ("build $builddir/linker-out: mkdir");
ninja.WriteLine ($"build {linker_ofiles}: linker");