Description
I have a problem using multithreading and packaging the resulting WASM in a reusable node package.
But let's start with what works so far:
I have a C++ program that I compile with emscripten, utilizing a CMakeLists.txt. I then want to use the resulting WASM in an npm package, for me to later publish.
These are my compiler flags:
-O0\
--bind\
--no-entry\
-s ALLOW_MEMORY_GROWTH=1\
-s MALLOC=emmalloc\
-s EXPORT_ES6=1\
-s MODULARIZE=1\
-s EXPORT_NAME=${PROJECT_NAME}\
-s SINGLE_FILE=1\
-s ENVIRONMENT=web,worker,shell\
--emit-tsd=${BUILD_FOLDER}/${PROJECT_NAME}.d.ts\
It outputs a .js and a .d.ts file, and I can use it like this:
import MainModule from "../wasm/wasmbuild/output/hello_world_web"
export const testHelloWorld = async () => {
const myMainModule = await MainModule()
return myMainModule._main(0, 0)
}
This works well!
However, now I want to add multithreading. I adjust my code, and add the following compiler flags to my CMakeLists.txt:
-pthread\
-s PTHREAD_POOL_SIZE=16\
When running the same way I do above, I get these errors in my console:
I have the strong suspicion, that it is because of this block in the generated .js file:
allocateUnusedWorker() {
var worker;
var workerOptions = {
"type": "module",
// This is the way that we signal to the Web Worker that it is hosting
// a pthread.
"name": "em-pthread"
};
// If we're using module output, use bundler-friendly pattern.
// We need to generate the URL with import.meta.url as the base URL of the JS file
// instead of just using new URL(import.meta.url) because bundler's only recognize
// the first case in their bundling step. The latter ends up producing an invalid
// URL to import from the server (e.g., for webpack the file:// path).
worker = new Worker(new URL("hello_world_web.js", import.meta.url), workerOptions); // <------ THIS
PThread.unusedWorkers.push(worker);
},
As I said, I use this in a package, I don't host the hello_world_web.js in any specific place. How would "hello_world_web.js" actually be found? Is there any specific way of handling this?
I already gave "locateFile" a go, like this:
const myMainModule = await MainModule({
locateFile: (path: string) => {
console.log("Trying to locate:")
return path
},
})
But nothing was logged, and since I don't see any "locateFile" referenced in the codeblock I mentioned, I didn't pursue this any further.
I also looked into webpack, and whether it would solve my issues. But that feels like overkill for what I want to achieve, and I have no clue if that is even the right path. So I didn't get further into that yet either.
Any help would be highly appreciated! Here's a simple repo to try things out: https://github.com/Andonvr/emscripten-threading-example.
Cheers.