diff --git a/blog/2024-09-25-js-link-c.md b/blog/2024-09-25-js-link-c.md new file mode 100644 index 00000000..f5698441 --- /dev/null +++ b/blog/2024-09-25-js-link-c.md @@ -0,0 +1,65 @@ +--- +slug: 2024-09-25-ghc-update +title: "Linking C code with GHC's JavaScript backend" +authors: [sylvain] +tags: [ghc,javascript] +--- + +Since GHC 9.10 it is possible to build and to link C code with Haskell code +compiled with the JavaScript backend. In this post we show to do it, using the +well-known SQLite database as an example. + + + +Using JavaScript code produced from C code from JavaScript code produced +from Haskell code is [documented in GHC's users +guide](https://downloads.haskell.org/ghc/latest/docs/users_guide/javascript.html#linking-with-c-sources), +however it's probably simpler to understand with examples. +We'll start with a simple Hello World example and then directly leap to an +example using the SQLite database. + +TODO: motivation. Why would we want to do that? Avoid reimplementing in Haskell. +Performance (need example + benchmark). Maybe a graphics C lib? + +## Hello World + +TODO + +## SQLite + +The SQLite database is released as a single C file. To use it from Haskell, we +can use the [direct-sqlite +package](https://hackage.haskell.org/package/direct-sqlite) which embeds this C +file and provides Haskell bindings for it. + +Since GHC 9.10, if the JavaScript backend on GHC is used, by default the C files +are compiled to WebAssembly (using the [Emscripten](https://emscripten.org/) +compiler) and embedded into the produced JavaScript file. (You can disable this +behavior by passing the `-ddisable-js-c-sources` flag to GHC.) + +The generated code can't be directly called into from Haskell. We need to write +some JavaScript code to call into the WebAssembly code, passing arguments into +the WebAssembly heap as needed. This is no as difficult as it should, especially +thanks to JavaScript helper functions provided by GHC's JavaScript RTS. + +## Building the project + +Note that we need to use at least GHC 9.10.2 for this to work as it contains a +fix for [#25288](https://gitlab.haskell.org/ghc/ghc/-/issues/25288). + +FIXME: checkout branch in fork instead? https://github.com/hsyl20/direct-sqlite/tree/hsyl20/js + +```bash +> git clone https://github.com/IreneKnapp/direct-sqlite -- FIXME: checkout MR +> cd direct-sqlite +> cabal build . -w /path/to/javascript-unknown-ghcjs-ghc --with-ghc-pkg=/path/to/javascript-unknown-ghcjs-ghc-pkg +> cabal test . -w /path/to/javascript-unknown-ghcjs-ghc --with-ghc-pkg=/path/to/javascript-unknown-ghcjs-ghc-pkg +Running 1 test suites... +Test suite test: RUNNING... +Cases: 25 Tried: 25 Errors: 0 Failures: 0 +Cases: 1 Tried: 1 Errors: 0 Failures: 0 +Cases: 26 Tried: 26 Errors: 0 Failures: 0 +Cases: 1 Tried: 1 Errors: 0 Failures: 0 +Test suite test: PASS +``` +