This guide provides instructions for building, running, and debugging CoreCLR on WebAssembly (WASM). This is experimental support and is currently under active development.
Make sure you've prepared your environment and installed all the requirements for your platform. If not, follow this link for the corresponding instructions.
To build the CoreCLR runtime for WebAssembly, use the following command from the repository root:
Linux/macOS:
./build.sh -os browser -c Debug -subset clr+libsWindows:
.\build.cmd -os browser -c Debug -subset clr+libsThis command will:
- Install the Emscripten SDK (emsdk) automatically
- Build the CoreCLR runtime for WebAssembly
- Build the required libraries
Note: The first build may take longer as it downloads and sets up the Emscripten toolchain.
To enable the browser workflow, edit src/coreclr/hosts/corerun/CMakeLists.txt and set the CORERUN_IN_BROWSER variable to 1.
You will also need to ensure the WASM_PRELOAD_DIR (see src/coreclr/hosts/corerun/CMakeLists.txt) is populated during a build of corerun so the virtual file system is created. This will require the copying of the libraries (see Console Testing details below) and HelloWorld.dll into ./artifacts/bin/coreclr/browser.wasm.Debug/IL and then the corerun project will then need to be rebuilt.
If you don't have dotnet-serve installed, you can install it as a global .NET tool with:
dotnet tool install --global dotnet-serveLinux/macOS:
dotnet-serve --directory "artifacts/bin/coreclr/browser.wasm.Debug"Windows:
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. The entry point is the corerun.html file. If you don't see corerun.html, you didn't set the CORERUN_IN_BROWSER variable when building the clr subset.
You can also run the runtime directly in Node.js:
In script below please replace /path/to/runtime/ by a absolute unix path to the actual runtime repo (even on Windows).
cp ./artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Debug/runtimes/browser-wasm/lib/net11.0/*.dll ./artifacts/bin/coreclr/browser.wasm.Debug/IL
cp helloworld.dll ./artifacts/bin/coreclr/browser.wasm.Debug/IL
cd ./artifacts/bin/coreclr/browser.wasm.Debug/
node ./corerun.js -c /path/to/runtime/artifacts/bin/coreclr/browser.wasm.Debug/IL /path/to/runtime/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dllYou can also run the corehost directly in Node.js:
cp ./artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Debug/runtimes/browser-wasm/lib/net11.0/*.dll ./artifacts/bin/coreclr/browser.wasm.Debug/corehost
cp helloworld.dll ./artifacts/bin/coreclr/browser.wasm.Debug/corehost
cd ./artifacts/bin/coreclr/browser.wasm.Debug/corehost
node ./main.mjsFor debugging CoreCLR WebAssembly code, the recommended approach is using Chrome browser with the C/C++ DevTools Support (DWARF) extension:
-
Install the Chrome extension:
-
Open Chrome DevTools (F12) while running your WebAssembly application
-
Set breakpoints in the Sources tab:
- Navigate to the WebAssembly modules
- You can step through C code, set breakpoints, and inspect WebAssembly linear memory
- The extension provides source-level debugging with DWARF debug information
Note: The debugging experience is not perfect but works most of the time. You can step through C code, set breakpoints, and inspect the WebAssembly linear memory.
VS Code, through Node.js, provides a good debugging option for WebAssembly CoreCLR:
-
Install the VS Code extension (Optional):
-
Create a launch.json configuration:
In config below please replace /path/to/runtime/ by a absolute unix path to the actual runtime repo (even on Windows).
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "corerun",
"skipFiles": [
"<node_internals>/**"
],
"outputCapture": "std",
"program": "corerun.js",
"env": {
"CORE_ROOT":"/path/to/runtime/artifacts/bin/coreclr/browser.wasm.Debug/IL/"
},
"runtimeArgs": [
"--stack-trace-limit=1000"
],
"args": [
"/path/to/runtime/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dll"
],
"cwd": "${workspaceFolder}/artifacts/bin/coreclr/browser.wasm.Debug/"
},
{
"name": "browserhost",
"type": "node",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"runtimeArgs": [
"--stack-trace-limit=1000"
],
"args": [
"HelloWorld.dll"
],
"outputCapture": "std",
"cwd": "${workspaceFolder}/artifacts/bin/coreclr/browser.wasm.Debug/corehost",
"program": "main.mjs",
}
]
}Note that for corerun path in the args and CORE_ROOT need to be absolute path on your host file system in unix format (even on Windows).
-
Copy managed DLLs
System.Runtime.dllandhelloworld.dllintoartifacts/bin/coreclr/browser.wasm.Debug/IL/. -
Set breakpoints in
corerun.jsin one of theput_charfunctions (thestdout/stderrimplementation) -
Start debugging and step through the WebAssembly code using the call stack
This approach allows you to debug the JavaScript host and step into WebAssembly code or into the C/C++ code if the Dwarf Debugging extension was installed.
- to display
WCHAR *strings in debugger watch window, cast it tochar16_t*like(char16_t*)pLoaderModule->m_fileName