GHC 的 wasm 后端现在支持 Template Haskell 和 ghci

两年前作者写了一篇博客宣布 GHC wasm 后端已合并到上游。自那以后一直懒得再写一篇关于该项目的博客,但项目并未停滞,有很多改进,包括:

  • 在代码生成器和运行时有许多 bug 修复,可通过上游 GHC CI 管道中的完整 GHC wasm 后端测试套件见证,如今的 GHC wasm 后端比 GHC - 9.6 时代更健壮。
  • 可以在 macOS 和 aarch64 - linux 主机上构建和测试 GHC wasm 后端。
  • 今年早些时候实现了 wasm 的 JSFFI 功能,可在 Haskell 和 JavaScript 之间相互调用,支持 Haskell 前端框架如 reflex 和 miso,并有示例 repo 展示。
  • GHC wasm 后端终于支持 Template Haskell 和 ghci。

展示代码的方式:

  • 使用 Nix 安装:nix shell 'gitlab:haskell-wasm/ghc-wasm-meta?host=gitlab.haskell.org',然后wasm32-wasi-ghc --interactive
  • 非 Nix 工作流:curl https://gitlab.haskell.org/haskell-wasm/ghc-wasm-meta/-/raw/master/bootstrap.sh | sh,设置环境后wasm32-wasi-ghc --interactive。两种安装方法默认使用 GHC HEAD,提供了 Linux 和 macOS 主机的二进制工件。

wasm 的 TH/ghci 支持状态总结:

  • 补丁已合并到 GHC master分支,从ghc - 9.12开始将出现在上游发布分支,作者在自己的 fork 中也有非官方的 backport 分支,ghc - wasm - meta打包的 GHC 发布分支 bindists 是从作者的分支构建的。
  • 仅涉及纯计算的 TH 拼接和简单文件 I/O 工作,副作用受 WASI 限制,ghci 也有相同限制。
  • wasm 动态链接器可加载字节码和编译代码,但只能加载 wasm 共享库,使用wasm32 - wasi - ghc编译涉及 TH 的代码时要传递- dynamic - too,使用wasm32 - wasi - cabal时要在全局配置文件中设置shared: True
  • wasm TH/ghci 功能至少需要cabal - 3.14,JSFFI 功能在 ghci 中也可用。
  • cabal 包中的c - sources/cxx - sources可在 TH/ghci 中链接和运行,但更复杂的 C/C++ 外部库依赖需要特殊处理。
  • ghci 的热重载和基本 REPL 功能可用,但调试器尚未工作。

幕后原理:

  • 通过传递- opti - vwasm32 - wasi - ghc,可以让外部解释器打印与主机 GHC 进程之间传递的所有消息,解释了涉及消息传递的原因是 GHC 交叉编译和评估 TH 拼接时需要加载和运行目标平台的代码,“外部解释器”运行在目标平台处理目标代码,通过消息传递与主机 GHC 交互。
  • 在 wasm 中,核心挑战是动态链接,之前的方法很缓慢且不支持跨拼接状态或 ghci,现在实现了自己的 wasm 动态链接器,支持加载 wasm 共享库,经过多个步骤实现了 GHC wasm 后端的全 TH 和 ghci 支持,包括加载libc.so、多个共享库、生成 wasm 位置无关代码等,GHC 构建系统和驱动也做了调整。

接下来的计划:

  • 支持在浏览器中通过puppeteer运行 wasm 外部解释器,实现 Haskell 前端实时编码。
  • 支持在浏览器中运行交互式 ghci 会话,创建真正的客户端 Haskell 游乐场。
  • 可能进一步提高性能。
  • 修复 ghci 调试器支持。欢迎加入 Haskell wasm Matrix 房间交流。
阅读 18
0 条评论