emscripten
应用 LLVM
编译器。emscripten 官网文档
环境要求
- python 2.7.12+,3 也能够。
- mime-type 媒体类型,application/wasm,能够通过 http 头验证。
装置
# 下载 emsdk 仓库git clone https://github.com/emscripten-core/emsdk.git && cd emsdk# 下载并装置 sdk./emsdk install latest# 激活最新 sdk./emsdk activate latest# 激活终端环境变量source ./emsdk_env.sh
也能够增加到环境变量中
# emsdkexport PATH=$PATH:$YOUR_DIR/emsdkexport PATH=$PATH:$YOUR_DIR/emsdk/node/14.18.2_64bit/binexport PATH=$PATH:$YOUR_DIR/emsdk/upstream/emscripten
验证
emsdk list
一个简略的 wasm 程序
calculate_prime.c
#ifdef __EMSCRIPTEN__ #include <emscripten.h>#endif#include <stdlib.h>#include <stdio.h>int IsPrime(int value) { int i; for (i = 2; i < value; i++) { if (value % i == 0) { return 0; } } return 1;}
int main(int argc, char **argv) { int start = 0; int end = 100; printf("prime number between %d and %d\n", start, end); for (int i = start; i < end; i++) { if (IsPrime(i)) { printf("%d is prime\n", i); } } return 0;}
</div>
</div>
编译 查看后果
emcc calculate_prime.c -o html_template.html
造成三个文件
html_template.htmlhtml_template.jshtml_template.wasm
html
次要蕴含了 wasm
的援用和实例化。通过 web API
以及 emsdk
通过 js
提供的工具进行运行。
当然也能够只生成 js
文件。
emcc calculate_prime.c -o js_plumbing.js
生成文件
js_plumbing.jsjs_plumbing.wasm
生成的 wasm
文件是二进制文件, 咱们能够通过将 wasm
转化成 wat
来进行浏览。
# https://github.com/webassembly/wabtwasm2wat js_plumbing.wasm -o js_plumbing.wat
关上会看到这样的代码片段。(如何浏览wasm?)
(module (type (;0;) (func (param i32 i32 i32) (result i32))) (type (;1;) (func (param i32) (result i32))) (type (;2;) (func (result i32))) (type (;3;) (func (param i32)))
wasm 与 javascript 交互
side_module.c
int Increment(int x) { return x + 1;}
编译
emcc side_module.c -s SIDE_MODULE=2 -O1 -s EXPORTED_FUNCTIONS=\["_Increment"\] -o side_module.wasm
-s SIDE_MODULE=2
: 将代码编译为副模块,并且emcc
不会在生成的模块中蕴含C
的规范库- 优化标记
-O1
,默认-O0
。-O0
保留无关函数;-O1
进行了tree sharking
;-O2
压缩并tree sharking
-s EXPORTED_FUNCTIONS=['_Increment']
指定Increment
为导出函数,须要后面减少_
,容许多个。*.wasm
后缀代表只生成webAssembly
文件。
index.js
来加载 wasm
const wasmBinaryFile = 'side_module.wasm'/** * WebAssembly.Memory * 蕴含内存、表、全局变量、函数援用等 */const env = { '__table_base': 0, 'memory': new WebAssembly.Memory({ initial: 256, maximum: 256 }), '__memory_base': 1024,};WebAssembly.instantiateStreaming( fetch(wasmBinaryFile), {env},).then(result => { const increment = result.instance.exports.Increment; console.log('get wasm export function:', increment); increment && console.log(increment(17).toString())})