WebAssembly 入门

本文最后更新于:2022年7月6日 上午

以下我们用简称 wasm 代替 WebAssembly

wasm 是什么

wasm 技术已经出来很久了,曾经也是引起了非常广泛的关注,发展历程就不一一展开了。作为 Web 支持的第四们语言来说,它可移植、体积小、加载快。说它是一门语言呢,也有点夸张,毕竟没有人会直接去写二进制,wasm 本身是被设计为高级编程语言的可移植编译目标。

所以我们会看到,目前有非常多的语言都提供了对应的编译器,可以很方便的把 javaRustGo等高级语言完美的编译为 wasm 并运行到浏览器中。当然,对于前端同学来说,这些语言还是会有一些门槛,不过我们也有 [AssemblyScript](https://www.assemblyscript.org/introduction.html) 语言来做相同的事情。

在使用之前呢,我们肯定要安装对应的工具,来达到把高级语言编译到 wasm 的目的,这里我主要讲两种,分别针对 C/C++ 以及 AssemblyScript。今天我们主要讲一下 C/C++ 对应的工具安装,注:以下均以 mac 电脑为例。

emsdk 安装

对于 C/C++ 的开发者来说,我们需要安装的编译工具就是 [emsdk](https://github.com/emscripten-core/emsdk)。按照文档上来说,具体有以下几步:

# 首先需要打开命令行,执行
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk

# 安装以及激活最新版本
./emsdk install latest
./emsdk activate latest

# 激活环境变量
source ./emsdk_env.sh

安装时遇到的问题

正常情况下,就安装 OK 了。但事情肯定不会就这么顺利,起码我在安装的时候就卡在了 ./emsdk install latest 这一步,一直报错 tar 命令解压 zip 包失败。这个时候我们就需要看一下这个安装脚本了。

首先,我们看一下 emsdk 这个项目的目录结构:

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4cff6da841264fb28fb41fcbc15593b3~tplv-k3u1fbpfcp-zoom-1.image

图中标注的部分即是我们需要重点关注的部分了,当我们运行 ./emsdk install latest 这条命令时,最终执行的是 emsdk.py 这个 python 脚本文件,脚本文件的具体逻辑大家感兴趣的可以自己看下,非常的简单。

./emsdk install latest 执行流程

具体来说,sdk 安装时会分为以下几步:

  • 就是根据我们命令行的参数,在 emscripten-releases-tags.json 文件中找到具体的 sdk 版本,我们的命令是 ./emsdk install latest ,那么此时命令行参数就是 latest
{
  "aliases": {
    "latest": "3.1.8",
    "latest-sdk": "latest",
    "latest-64bit": "latest",
    "sdk-latest-64bit": "latest",
    "latest-upstream": "latest",
    "latest-clang-upstream": "latest",
    "latest-releases-upstream": "latest"
  },
  "releases": {
    "3.1.8": "8c9e0a76ebed2c5e88a718d43e8b62452def3771",
    "3.1.8-asserts": "d33ae3c8d16f04b004b76c1d7c1989d637aa36e0",
    "3.1.7": "d0e637fe48197587d981f79e8114757731d0c2a9",
    "3.1.7-asserts": "88f0cab4e7db846e171cbbbbf20cc1a51b8c779f",
    "3.1.6": "8791c3e936141cbc2dd72d76290ea9b2726d39f3",
    "3.1.6-asserts": "84fa976d87a29ea1734601b042f3c6809ecb89f0",
    "3.1.5": "2dee36c7163f7394ab9341854ef5281501dd97d0",
    ...
   }
}

我们看到 latest 对应的版本是 3.1.8,同时也能获取到版本对应的 hash 值。

  • 找到版本号、hash 值的同时,命令行中的 latest 参数还会被解析为 releases-upstream-%releases-tag%
  • 同时,在 emsdk_manifest.json 文件中,sdks 里面有具体的环境依赖关系:
{
	....
	....
	"sdks": [
  ....,
  ....,
  {
    "version": "releases-upstream-%releases-tag%",
    "bitness": 64,
    "uses": ["node-14.18.2-64bit", "releases-upstream-%releases-tag%-64bit"],
    "os": "linux",
    "custom_install_script": "emscripten_npm_install"
  },
  {
    "version": "releases-upstream-%releases-tag%",
    "bitness": 64,
    "uses": ["node-14.18.2-64bit", "python-3.9.2-64bit", "releases-upstream-%releases-tag%-64bit"],
    "os": "macos",
    "arch": "x86_64",
    "custom_install_script": "emscripten_npm_install"
  },
	....
	....
	],
  ....
  ....
}

可以看到,versionreleases-upstream-%releases-tag%osmacos 时,会依赖 node-14.18.2python-3.9.2以及 releases-upstream-8c9e0a76ebed2c5e88a718d43e8b62452def3771

  • 根据各依赖版本,下载对应的包,并放在对应的目录下,比如:新建 node 目录,并在下载完 node-14.18.2 之后,以版本号为名新建子目录并解压到此目录中,python 同理:

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f9e816395bcd48609b3871a95ad8024d~tplv-k3u1fbpfcp-zoom-1.image

在子目录中,我们看到都会有一个 .emsdk_version 文件,其实里面的内容特别简单,就是记录一下当前依赖的版本号,脚本会读取这个文件来判断是否安装或更新了对应的依赖:

# node/14.18.2_64bit/.emsdk_version
node-14.18.2-64bit

解决方法

好了,到这里一切就很简单了,当我们运行 ./emsdk install latest 却遇到各种问题安装失败时,我们可以自行查看 emscripten-releases-tags.json 以及 emsdk_manifest.json 文件,查找到对应的依赖以及对应的版本,下载好之后按照上面的方式新建目录,放入内容,并新建.emsdk_version 放入版本号,就完成了。

如果找不到对应的版本怎么办?其实运行命令如果报错的话,命令行也会直接提示当前下载的是哪个版本,我们把链接拷贝出来自行下载也是可以的,链接示例参考如下:

#node-14.18.2-64bit
https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-darwin-x64.tar.gz
#python-3.9.2-64bit
https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/python-3.9.2-3-macos-x86_64.tar.gz
#releases-upstream-568a46a9fb7e1f1686a6f7216b3dc976f28d2a79-64bit
https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/568a46a9fb7e1f1686a6f7216b3dc976f28d2a79/wasm-binaries.tbz2

小结

当然,安装时没有任何问题时最好的。如果说安装时遇到不成功的情况,比如说 tar 解压缩 zip 包失败等问题,倒是可以参考一下。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

 目录