[wasi] Combine `main` function for the default and single file bundle (#85617)
authorAnkit Jain <radical@gmail.com>
Tue, 2 May 2023 18:39:46 +0000 (14:39 -0400)
committerGitHub <noreply@github.com>
Tue, 2 May 2023 18:39:46 +0000 (13:39 -0500)
.. case.

This was prompted by https://github.com/dotnet/runtime/issues/85616
where running `Invariant.Tests` breaks with:

```
Running /root/helix/work/correlation/wasmtime/wasmtime --dir=. --env=DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true dotnet.wasm WasmTestRunner managed/Invariant.Tests.dll -notrait category=IgnoreForCI -notrait category=OuterLoop -notrait category=failing

Unhandled Exception:
System.ArgumentException: Invalid argument 'managed/Invariant.Tests.dll'.
   at SimpleWasmTestRunner.Main(String[] args)
   at SimpleWasmTestRunner.<Main>(String[] args)
```

- This broke because of a recent change due to which setting
  `InvariantGlobalization=true` meant `WasmBuildNative=true`
- But this did not trigger single file bundle
- And the build ended up relinking a dotnet.wasm but using the
  single-file bundle `main` function.

Instead, we combine the two main functions and switch between the
behavior depending on compile time defines.

Fixes https://github.com/dotnet/runtime/issues/85616

src/mono/wasi/runtime/CMakeLists.txt
src/mono/wasi/runtime/driver.c
src/mono/wasi/runtime/main.c
src/mono/wasi/wasi.proj

index 2ae7cb2..08bb59b 100644 (file)
@@ -6,7 +6,7 @@ option(DISABLE_THREADS "defined if the build does NOT support multithreading" ON
 option(DISABLE_WASM_USER_THREADS "defined if the build does not allow user threads to be created in a multithreaded build" OFF)
 
 set(CMAKE_EXECUTABLE_SUFFIX ".wasm")
-add_executable(dotnet driver.c pinvoke.c stubs.c synthetic-pthread.c)
+add_executable(dotnet driver.c main.c pinvoke.c stubs.c synthetic-pthread.c)
 
 target_include_directories(dotnet PUBLIC ${MONO_INCLUDES} ${MONO_OBJ_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/include/wasm)
 target_compile_options(dotnet PUBLIC @${NATIVE_BIN_DIR}/src/wasi-default.rsp @${NATIVE_BIN_DIR}/src/wasi-compile.rsp -DGEN_PINVOKE=1)
index 33ce47c..52457c5 100644 (file)
@@ -720,46 +720,3 @@ mono_wasm_string_array_new (int size)
 {
        return mono_array_new (root_domain, mono_get_string_class (), size);
 }
-
-#ifdef _WASI_DEFAULT_MAIN
-/*
- * with wasmtime, this is run as:
- *  $ wasmtime run--dir . dotnet.wasm MainAssembly [args]
- *
- *
- * arg0: dotnet.wasm
- * arg1: MainAssembly
- * arg2-..: args
- */
-int main(int argc, char * argv[]) {
-       if (argc < 2) {
-               printf("Error: First argument must be the name of the main assembly\n");
-               return 1;
-       }
-
-       mono_set_assemblies_path("managed");
-       mono_wasm_load_runtime("", 0);
-
-       const char *assembly_name = argv[1];
-       MonoAssembly* assembly = mono_wasm_assembly_load (assembly_name);
-       if (!assembly) {
-               printf("Could not load assembly %s\n", assembly_name);
-               return 1;
-       }
-       MonoMethod* entry_method = mono_wasi_assembly_get_entry_point (assembly);
-       if (!entry_method) {
-               fprintf(stderr, "Could not find entrypoint in the assembly.\n");
-               exit(1);
-       }
-
-       MonoObject* out_exc;
-       MonoObject* out_res;
-       // Managed app will see: arg0: MainAssembly, arg1-.. [args]
-       int ret = mono_runtime_run_main(entry_method, argc - 1, &argv[1], &out_exc);
-       if (out_exc) {
-               mono_print_unhandled_exception(out_exc);
-               exit(1);
-       }
-       return ret < 0 ? -ret : ret;
-}
-#endif
index 9bd30d7..84ff115 100644 (file)
@@ -21,8 +21,38 @@ int main(int argc, char * argv[]) {
 #endif
        mono_wasm_load_runtime("", 0);
 
+       int arg_ofs = 0;
+#ifdef WASM_SINGLE_FILE
+       /*
+        * For single-file bundle, running with wasmtime:
+        *
+        *  $ wasmtime run --dir . MainAssembly.wasm [args]
+        *
+        * arg0: MainAssembly
+        * arg1-..: args
+        */
        const char* assembly_name = dotnet_wasi_getentrypointassemblyname();
        MonoAssembly* assembly = mono_assembly_open(assembly_name, NULL);
+#else
+       /*
+        * For default case which uses dotnet.wasm, running with wasmtime:
+        *
+        *  $ wasmtime run --dir . dotnet.wasm MainAssembly [args]
+        *
+        * arg0: dotnet.wasm
+        * arg1: MainAssembly
+        * arg2-..: args
+        */
+
+       const char *assembly_name = argv[1];
+       arg_ofs = 1;
+       MonoAssembly* assembly = mono_wasm_assembly_load (assembly_name);
+       if (!assembly) {
+               printf("Could not load assembly %s\n", assembly_name);
+               return 1;
+       }
+#endif
+
        MonoMethod* entry_method = mono_wasi_assembly_get_entry_point (assembly);
        if (!entry_method) {
                fprintf(stderr, "Could not find entrypoint in assembly %s\n", assembly_name);
@@ -31,7 +61,8 @@ int main(int argc, char * argv[]) {
 
        MonoObject* out_exc;
        MonoObject* out_res;
-       int ret = mono_runtime_run_main(entry_method, argc, argv, &out_exc);
+       // Managed app will see: arg0: MainAssembly, arg1-.. [args]
+       int ret = mono_runtime_run_main(entry_method, argc - arg_ofs, &argv[arg_ofs], &out_exc);
        if (out_exc)
        {
                mono_print_unhandled_exception(out_exc);
index ea89bec..69aad8f 100644 (file)
       <_WasiCompileFlags Include="-D_WASI_EMULATED_PROCESS_CLOCKS"/>
       <_WasiCompileFlags Include="-D_WASI_EMULATED_SIGNAL"/>
       <_WasiCompileFlags Include="-D_WASI_EMULATED_MMAN"/>
-      <_WasiCompileFlags Include="-D_WASI_DEFAULT_MAIN"/>
       <!-- keep in sync with src\mono\wasi\build\WasiApp.Native.targets -->
       <!-- keep stack-size in sync with wasm_get_stack_size until after https://github.com/llvm/llvm-project/commit/1532be98f99384990544bd5289ba339bca61e15b in WASI SDK -->
       <_WasiLinkFlags Include="-Wl,-z,stack-size=8388608,--initial-memory=52428800,-lwasi-emulated-process-clocks,-lwasi-emulated-signal,-lwasi-emulated-mman"/>