最近发现了 wasm-micro-runtime 这么个小玩意,一个超小的 wasm 运行时。随手记录下。
0. 先看全貌
在 wasm-micro-runtime (简称 wamr) 里要把一个程序从源文件一直到跑起来,会经历以下步骤:
1 | test.c --[wasi-sdk]-> test.wasm --[wamrc]-> test.aot --[iwasm]-> 跑起来 |
如你所见,现在我需要 wasi-sdk
wasmrc
iwasm
这仨玩意儿。
1.环境准备
1.1. 取得 wasi-sdk
现成的。在 https://github.com/WebAssembly/wasi-sdk/releases 找到对应你系统的版本下载解压即可。这里假设你把它解压到了 /opt/wasi-sdk
。实际上放哪无所谓。
1.2. 编译 iwasm
:wamr 运行时
wamr 官方已经提供了几个不同平台的运行时。我用 macOS,直接有现成的:
1 | cd product-mini/platforms/darwin |
你可能发现我的编译命令和官方的不一样…没错,cmake
本身就有 -B
和 --build
,大可不必手动 mkdir build && cd make
,多麻烦。而且 Ninja 香啊~
跑完,build/iwasm
就是当前平台的运行时。
1.3. 编译 wamrc
:AOT 编译器
先编译一遍 LLVM 的一些库,需要的时间比较久。不得不说,原版脚本用的是 GNU Makefiles 是真的慢…所以我又夹带了点私货
1 | diff --git a/build-scripts/build_llvm.py b/build-scripts/build_llvm.py |
跑它:
1 | python build-scripts/build_llvm.py --platform darwin --arch ARM X86 |
然后编译 wamrc
。这里我同样用 Ninja,比官方的命令快多了。
1 | cd wamr-compiler |
跑完,同样得到了 build/wamrc
。
2. 编译应用
先来个简单的程序,我假设它叫 test.c
:
1 |
|
编译它
1 | $ /opt/wasi-sdk/bin/clang -O3 -o test.wasm test.c |
现在,你得到了一个 test.wasm
文件了。理论上,你可以直接用 iwasm
去执行它。但我想玩玩 AOT。所以继续。
1 | $ ./wamrc -o test.aot test.wasm |
现在你得到了一个 test.aot
,执行它:
1 | $ ./iwasm test.aot |
完成!
3. 顺带一提
编译 wamrc
AOT 编译器之前,使用 build_llvm.py
编译 LLVM 运行库时所传入的参数,--platform
表示当前 (也就是运行 wamrc
的构建机) 平台,--arch
表示需要 wamrc
支持生成的目标架构。具体可选值可执行 build-scripts/build_llvm.py --help
查看。
如果你需要生成 Xtensa 目标,直接传入 --arch Xtensa
会遇到两个问题,需要额外处理一下。
一是由于 LLVM 的 Xtensa 支持目前还是试验阶段,需要一个宏打开:
1 | diff --git a/build-scripts/build_llvm.py b/build-scripts/build_llvm.py |
二是由于官方 llvm/llvm-project
不支持 Xtensa 目标,需要换成乐鑫的 espressif/llvm-project
。
1 | cd core/deps/llvm |
删掉 build
重新编译一下。
1 | rm -rf core/deps/llvm/build |