diff --git a/docs/workflow/building/coreclr/wasm.md b/docs/workflow/building/coreclr/wasm.md index b2c6caa2d495d6..4f10f4c6a438ff 100644 --- a/docs/workflow/building/coreclr/wasm.md +++ b/docs/workflow/building/coreclr/wasm.md @@ -48,12 +48,12 @@ dotnet tool install --global dotnet-serve **Linux/macOS:** ```bash -dotnet-serve --directory "artifacts/bin/coreclr/browser.wasm.Debug/corewasmrun" +dotnet-serve --directory "artifacts/bin/coreclr/browser.wasm.Debug" ``` **Windows:** ```cmd -dotnet-serve --directory "artifacts\bin\coreclr\browser.wasm.Debug\corewasmrun" +dotnet-serve --directory "artifacts\bin\coreclr\browser.wasm.Debug" ``` This will start a local HTTP server and you can open the provided URL in your browser. @@ -155,7 +155,7 @@ Note that for `corerun` path in the `args` and `CORE_ROOT` need to be **absolute 3. **Copy managed DLLs** `System.Runtime.dll` and `helloworld.dll` into `artifacts/bin/coreclr/browser.wasm.Debug/IL/`. -4. **Set breakpoints** in `corewasmrun.js` in one of the `put_char` functions (the `stdout`/`stderr` implementation) +4. **Set breakpoints** in `corerun.js` in one of the `put_char` functions (the `stdout`/`stderr` implementation) 5. **Start debugging** and step through the WebAssembly code using the call stack diff --git a/src/coreclr/hosts/corerun/CMakeLists.txt b/src/coreclr/hosts/corerun/CMakeLists.txt index 56aa91453621fe..f41afefcd30fc0 100644 --- a/src/coreclr/hosts/corerun/CMakeLists.txt +++ b/src/coreclr/hosts/corerun/CMakeLists.txt @@ -2,13 +2,15 @@ project(corerun) set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CORERUN_IN_BROWSER 0) + if(CLR_CMAKE_HOST_WIN32) add_definitions(-DFX_VER_INTERNALNAME_STR=corerun.exe) -else(CLR_CMAKE_HOST_WIN32) +else() include(configure.cmake) -endif(CLR_CMAKE_HOST_WIN32) +endif() -#Required to expose symbols for global symbol discovery. +# Required to expose symbols for global symbol discovery. set(CLR_CMAKE_KEEP_NATIVE_SYMBOLS TRUE) add_executable_clr(corerun @@ -33,36 +35,39 @@ if(CLR_CMAKE_HOST_WIN32) if (CLR_CMAKE_HOST_ARCH_AMD64) target_link_options(corerun PRIVATE "/CETCOMPAT") endif() -else(CLR_CMAKE_HOST_WIN32) +else() target_link_libraries(corerun PRIVATE ${CMAKE_DL_LIBS}) # Required to expose symbols for global symbol discovery target_link_libraries(corerun PRIVATE -rdynamic) - # Android implements pthread natively + # Android implements pthread natively. + # WASM, linking against pthreads indicates Node.js workers are + # enabled and not suitable for the browser. if(NOT CLR_CMAKE_TARGET_ANDROID AND NOT CLR_CMAKE_TARGET_ARCH_WASM) target_link_libraries(corerun PRIVATE pthread) endif() # Static linking if (CLR_CMAKE_TARGET_ARCH_WASM) - target_sources(corerun PRIVATE corerun.wasm.cpp) + target_sources(corerun PRIVATE ./wasm/pinvoke_override.cpp) + target_include_directories(corerun PRIVATE ./wasm/) target_link_libraries(corerun PRIVATE - coreclr_static - System.Native-Static - System.Native.TimeZoneData) + coreclr_static + System.Native-Static + System.Native.TimeZoneData) # linker options for NodeJs, link in JavaScript helper, access to local filesystem if (CLR_CMAKE_TARGET_BROWSER) - target_compile_options(corerun PRIVATE + target_compile_options(corerun PRIVATE -fwasm-exceptions -msimd128 ) - target_link_libraries(corerun PRIVATE + target_link_libraries(corerun PRIVATE System.Native.Browser-Static) set(JS_SYSTEM_NATIVE_BROWSER "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js") set(JS_SYSTEM_BROWSER_UTILS "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Browser.Utils.js") set(JS_CORE_RUN_PRE - "${CMAKE_CURRENT_SOURCE_DIR}/libCorerun.pre.js") + "${CMAKE_CURRENT_SOURCE_DIR}/wasm/libCorerun.pre.js") set_target_properties(corerun PROPERTIES LINK_DEPENDS "${JS_CORE_RUN_PRE};${JS_SYSTEM_NATIVE_BROWSER};${JS_SYSTEM_BROWSER_UTILS};" LINK_FLAGS "--pre-js ${JS_CORE_RUN_PRE} --js-library ${JS_SYSTEM_NATIVE_BROWSER} --js-library ${JS_SYSTEM_BROWSER_UTILS}" @@ -71,11 +76,30 @@ else(CLR_CMAKE_HOST_WIN32) -fwasm-exceptions -sEXIT_RUNTIME=1 -sINITIAL_MEMORY=134217728 - -sENVIRONMENT=node,shell -sSTACK_SIZE=5MB - -lnoderawfs.js - -lnodefs.js + -sENVIRONMENT=node,shell,web -Wl,-error-limit=0) + + if (CORERUN_IN_BROWSER) + # Include the virtual file system data for the + # browser scenario. + set(WASM_PRELOAD_DIR "${CMAKE_INSTALL_PREFIX}/IL") + if (EXISTS "${WASM_PRELOAD_DIR}") + target_link_options(corerun PRIVATE + --preload-file ${WASM_PRELOAD_DIR}@/) + endif() + else() + # If not running in the browser, add + # Node.js file system support. + target_link_options(corerun PRIVATE + -lnoderawfs.js + -lnodefs.js) + endif() + endif() + + if (CORERUN_IN_BROWSER) + # Install the HTML file for running in the browser. + install(FILES "./wasm/corerun.html" DESTINATION . COMPONENT hosts) endif() endif() endif(CLR_CMAKE_HOST_WIN32) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 2b8105f3b3081a..538d63b8cf1db7 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -10,8 +10,8 @@ #include "dotenv.hpp" #ifdef TARGET_WASM -#include "corerun.wasm.hpp" -#endif +#include +#endif // TARGET_WASM #include @@ -79,6 +79,7 @@ namespace envvar // - PROPERTY: corerun will pass the paths vias the TRUSTED_PLATFORM_ASSEMBLIES property // - EXTERNAL: corerun will pass an external assembly probe to the runtime for app assemblies // - Not set: same as PROPERTY + // - The TPA list as a platform delimited list of paths. The same format as the system's PATH env var. const char_t* appAssemblies = W("APP_ASSEMBLIES"); } @@ -167,7 +168,7 @@ static bool try_get_export(pal::mod_t mod, const char* symbol, void** fptr) *fptr = pal::get_module_symbol(mod, symbol); if (*fptr != nullptr) return true; -#else // !TARGET_WASM +#else // !TARGET_WASM if (!strcmp(symbol, "coreclr_initialize")){ *fptr = (void*)coreclr_initialize; return true; @@ -380,8 +381,7 @@ static int run(const configuration& config) } else { - pal::fprintf(stderr, W("Unknown value for APP_ASSEMBLIES environment variable: %s\n"), app_assemblies_env.c_str()); - return -1; + tpa_list = std::move(app_assemblies_env); } { @@ -492,8 +492,8 @@ static int run(const configuration& config) #ifdef TARGET_WASM // install the pinvoke override callback to resolve p/invokes to statically linked libraries - wasm_add_pinvoke_override(); -#endif + add_pinvoke_override(); +#endif // TARGET_WASM int result; result = coreclr_init_func( diff --git a/src/coreclr/hosts/corewasmrun/index.html b/src/coreclr/hosts/corerun/wasm/corerun.html similarity index 63% rename from src/coreclr/hosts/corewasmrun/index.html rename to src/coreclr/hosts/corerun/wasm/corerun.html index 7fecf3afe85302..99bae741f7e14b 100644 --- a/src/coreclr/hosts/corewasmrun/index.html +++ b/src/coreclr/hosts/corerun/wasm/corerun.html @@ -2,17 +2,29 @@ - corewasmrun + corerun-wasm -

corewasmrun

+

corerun-wasm


     
-    
+    
 
diff --git a/src/coreclr/hosts/corerun/libCorerun.pre.js b/src/coreclr/hosts/corerun/wasm/libCorerun.pre.js
similarity index 72%
rename from src/coreclr/hosts/corerun/libCorerun.pre.js
rename to src/coreclr/hosts/corerun/wasm/libCorerun.pre.js
index fefba3db358fd1..b38606f0b06c19 100644
--- a/src/coreclr/hosts/corerun/libCorerun.pre.js
+++ b/src/coreclr/hosts/corerun/wasm/libCorerun.pre.js
@@ -4,12 +4,17 @@ var dotnetInternals = [
     },
     [],
 ];
-Module.preRun = () => {
+var basePreRun = () => {
     // copy all node/shell env variables to emscripten env
     if (globalThis.process && globalThis.process.env) {
         for (const [key, value] of Object.entries(process.env)) {
             ENV[key] = value;
         }
     }
+
     ENV["DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"] = "true";
-};
\ No newline at end of file
+};
+
+// Append to or set the preRun array
+Module.preRun = Module.preRun || [];
+Module.preRun.push(basePreRun);
\ No newline at end of file
diff --git a/src/coreclr/hosts/corerun/corerun.wasm.cpp b/src/coreclr/hosts/corerun/wasm/pinvoke_override.cpp
similarity index 87%
rename from src/coreclr/hosts/corerun/corerun.wasm.cpp
rename to src/coreclr/hosts/corerun/wasm/pinvoke_override.cpp
index 6e383db9206a12..26cc0d7a426806 100644
--- a/src/coreclr/hosts/corerun/corerun.wasm.cpp
+++ b/src/coreclr/hosts/corerun/wasm/pinvoke_override.cpp
@@ -11,7 +11,7 @@ extern "C" const void* SystemResolveDllImport(const char* name);
 
 // pinvoke_override:
 // Check if given function belongs to one of statically linked libraries and return a pointer if found.
-const void* pinvoke_override(const char* library_name, const char* entry_point_name)
+static const void* pinvoke_override(const char* library_name, const char* entry_point_name)
 {
     // This function is only called with the library name specified for a p/invoke, not any variations.
     // It must handle exact matches to the names specified. See Interop.Libraries.cs for each platform.
@@ -23,7 +23,7 @@ const void* pinvoke_override(const char* library_name, const char* entry_point_n
     return nullptr;
 }
 
-void wasm_add_pinvoke_override()
+void add_pinvoke_override()
 {
     PInvokeOverride::SetPInvokeOverride(pinvoke_override, PInvokeOverride::Source::RuntimeConfiguration);
 }
diff --git a/src/coreclr/hosts/corerun/corerun.wasm.hpp b/src/coreclr/hosts/corerun/wasm/pinvoke_override.hpp
similarity index 51%
rename from src/coreclr/hosts/corerun/corerun.wasm.hpp
rename to src/coreclr/hosts/corerun/wasm/pinvoke_override.hpp
index 302ef58542ac83..2ce458567c51ed 100644
--- a/src/coreclr/hosts/corerun/corerun.wasm.hpp
+++ b/src/coreclr/hosts/corerun/wasm/pinvoke_override.hpp
@@ -1,9 +1,9 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-#ifndef __CORERUN_WASM_HPP__
-#define __CORERUN_WASM_HPP__
+#ifndef __PINVOKE_OVERRIDE_HPP__
+#define __PINVOKE_OVERRIDE_HPP__
 
-void wasm_add_pinvoke_override();
+void add_pinvoke_override();
 
-#endif // __CORERUN_WASM_HPP__
+#endif // __PINVOKE_OVERRIDE_HPP__
diff --git a/src/coreclr/hosts/corewasmrun/CMakeLists.txt b/src/coreclr/hosts/corewasmrun/CMakeLists.txt
deleted file mode 100644
index a8ed9e8c996f8b..00000000000000
--- a/src/coreclr/hosts/corewasmrun/CMakeLists.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-project(corewasmrun)
-
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
-
-add_executable_clr(corewasmrun
-  corewasmrun.cpp
-  ../corerun/corerun.wasm.cpp
-)
-
-set(_WASM_PRELOAD_DIR "${CMAKE_INSTALL_PREFIX}/IL")
-if (EXISTS "${_WASM_PRELOAD_DIR}")
-  set(_WASM_PRELOAD_FILE --preload-file ${_WASM_PRELOAD_DIR}@/)
-endif (EXISTS "${_WASM_PRELOAD_DIR}")
-
-target_include_directories(corewasmrun PRIVATE
-  ../corerun
-)
-
-target_compile_options(corewasmrun PRIVATE 
-  -fwasm-exceptions
-  -msimd128
-  )
-
-set(JS_SYSTEM_NATIVE_BROWSER
-    "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js")
-set(JS_SYSTEM_BROWSER_UTILS
-    "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Browser.Utils.js")
-set(JS_CORE_WASM_RUN_PRE
-    "${CMAKE_CURRENT_SOURCE_DIR}/libCorewasmrun.pre.js")
-set_target_properties(corewasmrun PROPERTIES
-  LINK_DEPENDS "${JS_CORE_WASM_RUN_PRE};${JS_SYSTEM_NATIVE_BROWSER};${JS_SYSTEM_BROWSER_UTILS};"
-  LINK_FLAGS "--pre-js ${JS_CORE_WASM_RUN_PRE} --js-library ${JS_SYSTEM_NATIVE_BROWSER} --js-library ${JS_SYSTEM_BROWSER_UTILS}"
-  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
-target_link_options(corewasmrun PRIVATE
-  -fwasm-exceptions
-  -sEXIT_RUNTIME=1
-  -sINITIAL_MEMORY=134217728
-  -sSTACK_SIZE=5MB
-  -sFORCE_FILESYSTEM=1
-  ${_WASM_PRELOAD_FILE}
-  -Wl,-error-limit=0)
-target_link_libraries(corewasmrun PRIVATE
-  coreclr_static
-  System.Native.Browser-Static
-  System.Native-Static
-  System.Native.TimeZoneData)
-
-# The corerun version for wasm is being installed in its own directory
-# because it is an executable that comes with an index.html and we
-# want to avoid clashes.
-install_clr(TARGETS corewasmrun DESTINATIONS corewasmrun COMPONENT hosts)
-install(FILES index.html DESTINATION corewasmrun COMPONENT hosts)
diff --git a/src/coreclr/hosts/corewasmrun/corewasmrun.cpp b/src/coreclr/hosts/corewasmrun/corewasmrun.cpp
deleted file mode 100644
index 02ba088cfd5996..00000000000000
--- a/src/coreclr/hosts/corewasmrun/corewasmrun.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#include 
-#include 
-#include 
-
-#include "corerun.wasm.hpp"
-
-static void log_error_info(const char* line)
-{
-    std::fprintf(stderr, "log error: %s\n", line);
-}
-
-// The current CoreCLR instance details.
-static void* CurrentClrInstance;
-static unsigned int CurrentAppDomainId;
-
-static int run()
-{
-    const char* exe_path = "/";
-    const char* app_domain_name = "corewasmrun";
-    const char* entry_assembly = "ManagedAssembly.dll";
-
-    // Set base initialization properties.
-    std::vector propertyKeys;
-    std::vector propertyValues;
-
-    propertyKeys.push_back("TRUSTED_PLATFORM_ASSEMBLIES");
-    propertyValues.push_back("/HelloWorld.dll:/System.Private.CoreLib.dll:/System.Runtime.dll:/System.Console.dll:/System.Threading.dll:/System.Runtime.InteropServices.dll");
-    propertyKeys.push_back("NATIVE_DLL_SEARCH_DIRECTORIES");
-    propertyValues.push_back("/:.:");
-
-    coreclr_set_error_writer(log_error_info);
-
-    wasm_add_pinvoke_override();
-
-    printf("BEGIN: call coreclr_initialize\n");
-    int retval = coreclr_initialize(exe_path, app_domain_name, (int)propertyKeys.size(), propertyKeys.data(), propertyValues.data(), &CurrentClrInstance, &CurrentAppDomainId);
-    printf("END: call coreclr_initialize\n");
-
-    if (retval < 0)
-    {
-        std::fprintf(stderr, "coreclr_initialize failed - Error: 0x%08x\n", retval);
-        return -1;
-    }
-    else
-    {
-        printf("coreclr_initialize succeeded - retval: 0x%08x\n", retval);
-    }
-
-    int exit_code;
-    printf("BEGIN: call coreclr_execute_assembly\n");
-    retval = coreclr_execute_assembly(CurrentClrInstance, CurrentAppDomainId, 0, nullptr, "HelloWorld.dll", (uint32_t*)&exit_code);
-    printf("END: call coreclr_execute_assembly\n");
-
-    if (retval < 0)
-    {
-        std::fprintf(stderr, "coreclr_execute_assembly failed - Error: 0x%08x\n", retval);
-        return -1;
-    }
-
-    int latched_exit_code = 0;
-    printf("BEGIN: call coreclr_shutdown_2\n");
-    retval = coreclr_shutdown_2(CurrentClrInstance, CurrentAppDomainId, &latched_exit_code);
-    printf("END: call coreclr_shutdown_2\n");
-    if (retval < 0)
-    {
-        std::fprintf(stderr, "coreclr_shutdown_2 failed - Error: 0x%08x\n", retval);
-        exit_code = -1;
-    }
-
-    return retval;
-}
-
-int main()
-{
-    int retval = run();
-
-    return retval;
-}
diff --git a/src/coreclr/hosts/corewasmrun/libCorewasmrun.pre.js b/src/coreclr/hosts/corewasmrun/libCorewasmrun.pre.js
deleted file mode 100644
index 50a7e3b2d47225..00000000000000
--- a/src/coreclr/hosts/corewasmrun/libCorewasmrun.pre.js
+++ /dev/null
@@ -1,9 +0,0 @@
-var dotnetInternals = [
-    {
-        Module: Module,
-    },
-    [],
-];
-Module.preRun = () => {
-    ENV["DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"] = "true";
-};
\ No newline at end of file