两年前作者写了一篇博客宣布 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 - v到wasm32 - 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 房间交流。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。