How can I use cabal build-type: Hooks in Wasm build?

I have a build-type: Hooks cabal package that generates some source files as part of the build by exec-ing some external programs for generating the code. This all works perfectly fine when building with x64 ghc. However, when building against Wasm I get a linker error because cabal is compiling the setup binary with the -threaded flag causing the linker to try to link against the threaded ghc runtime, which IIUC doesn’t exist for Wasm.

[3 of 3] Linking /root/magic-the-haskelling/dist-newstyle/build/wasm32-wasi/ghc-9.12.2.20250327/api-0.1.0.0/setup/setup.wasm
wasm-ld: error: unable to find library -lHSrts-1.0.2_thr
wasm32-wasi-clang: error: linker command failed with exit code 1 (use -v to see invocation)
wasm32-wasi-ghc-9.12.2.20250327: wasm32-wasi-clang' failed in phase Linker’. (Exit code: 1)
HasCallStack backtrace:
bracket, called at compiler/GHC/Driver/Make.hs:2959:3 in ghc-9.12.2.20250327-inplace:GHC.Driver.Make

Error: [Cabal-7125]
Failed to build api-0.1.0.0-inplace. The failure occurred during the configure step.
CallStack (from HasCallStack):
dieWithException, called at src/Distribution/Client/ProjectOrchestration.hs:1241:21 in cabal-install-3.14.1.1-inplace:Distribution.Client.ProjectOrchestration

If I run the command without -threaded then it links successfully.

Is there any way to customize how cabal builds this setup binary, or some other way to get unstuck?

So I hacked on cabal-install a bit. I removed the -threaded flag from the call to the setup binary, and this allowed cabal-install to link it successfully. Then I fixed a naming issue where the generated binary is called setup.wasm but cabal-install was trying to invoke it without the .wasm extension. Then I hit the actual problem of running a .wasm binary on linux - obviously linux can’t execute it like a native binary without something like binfmt_misc. binfmt_misc would work I think, but setup binaries require the ability deeply interact with the host - access files, environment variables, child processes, etc. Using wasmtime I could grant filesystem access easily enough, and env vars, but I can’t spawn child processes (e.g. ghc) that setup needs. With wasmer I can’t even get tail calls working. So at this point I feel pretty confident in saying that building setup for the host platform is probably the wrong approach. Would be much better (for me at least) to build the setup executable for the build platform. Unfortunately, the only compiler cabal-install knows about is for the target platform, which is wasm, so I think I am stuck here.

1 Like