Import javascript in wasm backend: duplicate symbol

I’m trying to call a JavaScript function from code compiled with the WebAssembly backend:

-- Main.hs

import GHC.Wasm.Prim

foreign import javascript unsafe "console.log($1)"
  console_log :: JSString -> IO ()

foreign export ccall f :: Int -> Int

f :: Int -> Int
f x = x + 1

main :: IO ()
main = return ()

Unfortunately the compilation fails:

$ wasm32-wasi-ghc --make Main.hs -o main.wasm -optl-mexec-model=reactor -optl-Wl,--export=hs_init
[1 of 2] Compiling Main             ( Main.hs, Main.o )
[2 of 2] Linking main.wasm [Objects changed]
wasm-ld: error: duplicate symbol: main
>>> defined in /tmp/nix-shell.C184Kw/ghc1568321_0/ghc_7.o
>>> defined in /nix/store/kn9nmjbzk97dpg34ad1lmy0301i3gvwr-wasm32-wasi-ghc-gmp/lib/wasm32-wasi-ghc-9.9.20240219/lib/../lib/wasm32-wasi-ghc-9.9.20240219/rts-1.0.2/libHSrts-1.0.2.a(JSFFI.o)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
wasm32-wasi-ghc-9.9.20240219: `clang' failed in phase `Linker'. (Exit code: 1)

Removing either the import of console_log or the export of f, as well as replacing JSString with Int, makes the error go away.

What am I doing wrong?

You can fix this by specifying -no-hs-main in your call to wasm32-wasi-ghc, also see the corresponding section in the GHC User’s Guide.

2 Likes

This worked indeed, thanks!