Using the wasm-experimental workload it shoudl be possible to create multi-threaded wasmbrowser projects in .NET 7 RC1
Issues:
Detailed reproduction steps
- Download a net7 RC 1 nightly tar.gz from dotnet/installer (I used the "Release/7.0.1xx-rc1 (7.0.x Runtime)" column)
- Unpack into
${HOME}/work/net7-nightly
- Set
DOTNET_ROOT and PATH:
export DOTNET_ROOT="${HOME}/work/net7-nightly"
export PATH="${DOTNET_ROOT}:${PATH}"
- Create the directory
${HOME}/work/net7-playground and add the following into ${HOME}/work/net7-playground/NuGet.config
<configuration>
<packageSources>
<add key="dotnet7" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json" />
</packageSources>
</configuration>
- From the
net7-playground directory (so that NuGet.config is in the current dir), install the wasm-experimental workload:
cd ~/work/net7-playground
dotnet workload install wasm-experimental
- Make a sample project directory
${HOME}/work/net7-playground/hithread and create a wasmbrowser project:
cd ~/work/net7-playground
mkdir hithread
cd hithread
dotnet new wasmbrowser
- Bug 1 note that there is
browser.csproj not hithread.csproj - other templates create a .csproj file with the same name as the directory.
- Bug 2 create the missing
runtimeconfig.template.json with teh following content
{
"wasmHostProperties": {
"perHostConfig": [
{
"name": "browser",
"html-path": "index.html",
"Host": "browser"
}
]
}
}
- Add the follwoing to your
browser.csproj
<PropertyGroup>
<WasmEnableThreads>true</WasmEnableThreads>
<WasmEnableThreading>true</WasmEnableThreading>
<WasmBuildNative>true</WasmBuildNative>
</PropertyGroup>
Bug 3 note that WorkloadManifest.targets.in has a typo and uses WasmEnableThreading instead of WasmEnableThreads
- Run
dotnet build
$ dotnet build
MSBuild version 17.4.0-preview-22416-02+5d102ae37 for .NET
Determining projects to restore...
Restored /Users/alklig/work/net7-playground/hithread/browser.csproj (in 2 ms).
/Users/alklig/work/net7-nightly/sdk/7.0.100-rc.2.22425.5/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.RuntimeIdentifierInference.targets(219,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [/Users/alklig/work/net7-playground/hithread/browser.csproj]
browser -> /Users/alklig/work/net7-playground/hithread/bin/Debug/net7.0/browser-wasm/browser.dll
Compiling native assets with emcc with -O0. This may take a while ...
[2/3] corebindings.c -> corebindings.o [took 0.384s]
[1/3] pinvoke.c -> pinvoke.o [took 0.384s]
[3/3] driver.c -> driver.o [took 0.416s]
Linking for initial memory $(EmccInitialHeapSize)=536870912 bytes. Set this msbuild property to change the value.
Linking with emcc with -O0. This may take a while ...
...
Exception: FROZEN_CACHE is set, but cache file is missing: "sysroot/lib/wasm32-emscripten/libGL-mt.a" (in cache root path "/Users/alklig/work/net7-nightly/packs/Microsoft.NET.Runtime.Emscripten.3.1.12.Sdk.osx-x64/8.0.0-alpha.1.22415.5/tools/emscripten/cache")
/Users/alklig/work/net7-nightly/packs/Microsoft.NET.Runtime.WebAssembly.Sdk/7.0.0-rc.1.22422.12/Sdk/WasmApp.Native.targets(422,5): error MSB3073: The command "emcc "@/Users/alklig/work/net7-nightly/packs/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm/7.0.0-rc.1.22422.12/runtimes/browser-wasm/native/src/emcc-default.rsp" "@/Users/alklig/work/net7-nightly/packs/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm/7.0.0-rc.1.22422.12/runtimes/browser-wasm/native/src/emcc-link.rsp" "@/Users/alklig/work/net7-playground/hithread/obj/Debug/net7.0/browser-wasm/wasm/for-build/emcc-link.rsp"" exited with code 1. [/Users/alklig/work/net7-playground/hithread/browser.csproj]
Bug 4 We removed the *-mt.a static libraries in our EMSDK pack
9. Copy *-mt.a from an upstream EMSDK install into the emsdk pack:
cp ~/work/dotnet-runtime/runtime/src/mono/wasm/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/*-mt.a ~/work/net7-nightly/packs/Microsoft.NET.Runtime.Emscripten.3.1.12.Sdk.osx-x64/8.0.0-alpha.1.22415.5/tools/emscripten/cache/sysroot/lib/wasm32-emscripten
dotnet build should now succeed.
dotnet run shoudl serve the app. Open the URL in Chrome and open dev tools and hit reload. You should see something like this in the console:
MONO_WASM: worker initializing essential C exports and APIs
MONO_WASM: worker initializing essential C exports and APIs
MONO_WASM: worker initializing essential C exports and APIs
MONO_WASM: worker initializing essential C exports and APIs
dotnet.js:5 MONO_WASM: afterLoadWasmModuleToWorker added message event handler Worker {onmessage: ƒ, onerror: ƒ}
dotnet.js:5 MONO_WASM: afterLoadWasmModuleToWorker added message event handler Worker {onmessage: ƒ, onerror: ƒ}
dotnet.js:5 MONO_WASM: afterLoadWasmModuleToWorker added message event handler Worker {onmessage: ƒ, onerror: ƒ}
dotnet.js:5 MONO_WASM: afterLoadWasmModuleToWorker added message event handler Worker {onmessage: ƒ, onerror: ƒ}
dotnet.js:5 MONO_WASM: worker initializing essential C exports and APIs
dotnet.js:5 MONO_WASM: worker initializing essential C exports and APIs
dotnet.js:5 MONO_WASM: worker initializing essential C exports and APIs
dotnet.js:5 MONO_WASM: worker initializing essential C exports and APIs
dotnet.js:3 mono_wasm_runtime_ready fe00e07a-5519-4dfe-b35a-f867dbaf2e28
dotnet.js:2013 Hello, Console!
- Clean the
bin and obj directories.
Change the browser.csproj like this:
<PropertyGroup>
<WasmEnableThreads>true</WasmEnableThreads>
<WasmEnableThreading>true</WasmEnableThreading>
<WasmGenerateAppBundle>true</WasmGenerateAppBundle>
</PropertyGroup>
That is, replace WasmBuildNative by WasmGenerateAppBundle
12. run dotnet build again. Note that dotnet.worker.js isn't in the AppBundle directory. When running
the app prints 404s when trying to load it. From the Chrome DevTools console:
GET http://127.0.0.1:9000/dotnet.worker.js 404 (Not Found)
dotnet.worker.js:1 GET http://127.0.0.1:9000/dotnet.worker.js 404 (Not Found)
dotnet.worker.js:1 GET http://127.0.0.1:9000/dotnet.worker.js 404 (Not Found)
dotnet.worker.js:1 GET http://127.0.0.1:9000/dotnet.worker.js 404 (Not Found)
dotnet.js:5 MONO_WASM: afterLoadWasmModuleToWorker added message event handler Worker {onmessage: ƒ, onerror: ƒ}
dotnet.js:5 MONO_WASM: afterLoadWasmModuleToWorker added message event handler Worker {onmessage: ƒ, onerror: ƒ}
dotnet.js:5 MONO_WASM: afterLoadWasmModuleToWorker added message event handler Worker {onmessage: ƒ, onerror: ƒ}
dotnet.js:5 MONO_WASM: afterLoadWasmModuleToWorker added message event handler Worker {onmessage: ƒ, onerror: ƒ}
Using the
wasm-experimentalworkload it shoudl be possible to create multi-threadedwasmbrowserprojects in .NET 7 RC1Issues:
mainby [wasm-mt] Fix pack/build issues in threaded builds #75162 and onrelease/7.0by [release/7.0][wasm-mt] Fix pack/build issues in threaded builds #75171WasmGenerateAppBundledoesn't create multi-threaded builds withWasmEnableThreads- onlyWasmBuildNativedoes - due todotnet.worker.jsmissing from the runtime packWorkloadManifest.targets.inusesWasmEnableThreadinginstead ofWasmEnableThreadsmultithreadandperftracebuild variants don't define the correct feature flags.dotnet new wasmbrowsercreatesbrowser.csproj, not<dirname>.csprojthis looks like a local caching issuedotnet new wasmbrowserdoes not createruntimeconfig.template.jsonrequired fordotnet runDetailed reproduction steps
${HOME}/work/net7-nightlyDOTNET_ROOTandPATH:${HOME}/work/net7-playgroundand add the following into${HOME}/work/net7-playground/NuGet.confignet7-playgrounddirectory (so thatNuGet.configis in the current dir), install thewasm-experimentalworkload:${HOME}/work/net7-playground/hithreadand create awasmbrowserproject:browser.csprojnothithread.csproj- other templates create a .csproj file with the same name as the directory.runtimeconfig.template.jsonwith teh following content{ "wasmHostProperties": { "perHostConfig": [ { "name": "browser", "html-path": "index.html", "Host": "browser" } ] } }browser.csprojWorkloadManifest.targets.inhas a typo and usesWasmEnableThreadinginstead ofWasmEnableThreadsdotnet buildBug 4 We removed the
*-mt.astatic libraries in our EMSDK pack9. Copy
*-mt.afrom an upstream EMSDK install into the emsdk pack:cp ~/work/dotnet-runtime/runtime/src/mono/wasm/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/*-mt.a ~/work/net7-nightly/packs/Microsoft.NET.Runtime.Emscripten.3.1.12.Sdk.osx-x64/8.0.0-alpha.1.22415.5/tools/emscripten/cache/sysroot/lib/wasm32-emscriptendotnet buildshould now succeed.dotnet runshoudl serve the app. Open the URL in Chrome and open dev tools and hit reload. You should see something like this in the console:binandobjdirectories.Change the
browser.csprojlike this:That is, replace
WasmBuildNativebyWasmGenerateAppBundle12. run
dotnet buildagain. Note thatdotnet.worker.jsisn't in the AppBundle directory. When runningthe app prints 404s when trying to load it. From the Chrome DevTools console: