1. 概述
WebAssembly是一个可移植、体积小、加载快并且兼容 Web 的全新的格式。其有几个特点:高效、安全、开放、标准。
是由主流浏览器厂商组成的W3C 社区团体制定的一个新的规范。
1.1 开放
WebAssembly 有一套完整的语义,实际上 wasm 是体积小且加载快的一种二进制格式, 其目标就是充分发挥硬件的能力达到媲美原生的执行效率。
1.2 安全
WebAssembly 运行在一个沙箱化的执行环境中,甚至可以在现有的 JS 虚拟机中实现。在web环境中,WebAssembly将会严格遵守同源策略以及浏览器的安全策略。
1.3 开放
WebAssembly 设计了一个非常规整的文本格式用来测试、学习、调试、实验、优化、教学或者编写程序等。可以用这种文本格式在web页面上查看wasm模块的源码。
1.4 标准
WebAssembly 在 web 中被设计成无版本、特性可测试、向后兼容的。WebAssembly 可以被 JS 调用,进入 JavaScript Context,也可以像 Web API 一样调用浏览器的功能。当然,WebAssembly 不仅可以运行在浏览器上,也可以运行在非web环境下。
2. 开发者引导
2.1 前置准备
接下来,我们试着将一个简单的程序编译成 WebAssembly。想要编译成WebAssembly,首先我们需要先编译 LLVM。这是运行后续工具的先决条件。
- Git。Linux 和 OS X 系统中已经默认装好了,在 Windows 上需要手动安全一下。
- CMake。在 Linux 和 OS X系统中,我们可以使用包管理工具 apt-get 或 brew 来安装。
- 系统编译工具。Linux上,安装 GCC。OS X 上,安装 Xcode。Windows 上安装 Visual Studio 2015 Community with Update 3 或更新版本。
- Python 2.7.x,在 Linux 和 OS X上,很可能已经装好了。
安装完毕后,确认 git,cmake 和 python 已经在你的环境变量里,可以使用。
2.2 编译 Emscripten
通过 Emscripten SDK 构建 Emscripten 是自动的,操作如下。
代码语言:javascript复制$ git clone https://github.com/juj/emsdk.git
$ cd emsdk
$ ./emsdk install sdk-incoming-64bit binaryen-master-64bit
$ ./emsdk activate sdk-incoming-64bit binaryen-master-64bit
注意,以上步骤是官网给出的,但是我本人在运行到第三步的时候,会报错,错误如下:
后面通过查找问题,发现这是官方中文文档的坑,第三步在英文原版是:
代码语言:javascript复制# Download and install the latest SDK tools.
./emsdk install latest
# Make the "latest" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate latest
于是按照英文文档执行,执行成功:
代码语言:javascript复制[leooliliu@LEOOLILIU-MB0 emsdk % ./emsdk install latest
Resolving SDK alias 'latest' to '3.1.26'
Resolving SDK version '3.1.26' to 'sdk-releases-upstream-4f68bb2a505c727bcf58195cf4da20592a6e92c8-64bit'
Installing SDK 'sdk-releases-upstream-4f68bb2a505c727bcf58195cf4da20592a6e92c8-64bit'..
Installing tool 'node-14.18.2-64bit'..
Downloading: /Users/leooliliu/tencent/webassembly/emsdk/zips/node-v14.18.2-darwin-x64.tar.gz from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-darwin-x64.tar.gz, 32076686 Bytes
Unpacking '/Users/leooliliu/tencent/webassembly/emsdk/zips/node-v14.18.2-darwin-x64.tar.gz' to '/Users/leooliliu/tencent/webassembly/emsdk/node/14.18.2_64bit'
Done installing tool 'node-14.18.2-64bit'.
Installing tool 'python-3.9.2-64bit'..
Downloading: /Users/leooliliu/tencent/webassembly/emsdk/zips/python-3.9.2-3-macos-x86_64.tar.gz from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/python-3.9.2-3-macos-x86_64.tar.gz, 31899321 Bytes
Unpacking '/Users/leooliliu/tencent/webassembly/emsdk/zips/python-3.9.2-3-macos-x86_64.tar.gz' to '/Users/leooliliu/tencent/webassembly/emsdk/python/3.9.2_64bit'
Done installing tool 'python-3.9.2-64bit'.
Installing tool 'releases-upstream-4f68bb2a505c727bcf58195cf4da20592a6e92c8-64bit'..
Downloading: /Users/leooliliu/tencent/webassembly/emsdk/zips/4f68bb2a505c727bcf58195cf4da20592a6e92c8-wasm-binaries.tbz2 from https://storage.googleapis.com/webassembly/emscripten-releases-builds/mac/4f68bb2a505c727bcf58195cf4da20592a6e92c8/wasm-binaries.tbz2, 368504209 Bytes
Unpacking '/Users/leooliliu/tencent/webassembly/emsdk/zips/4f68bb2a505c727bcf58195cf4da20592a6e92c8-wasm-binaries.tbz2' to '/Users/leooliliu/tencent/webassembly/emsdk/upstream'
Done installing tool 'releases-upstream-4f68bb2a505c727bcf58195cf4da20592a6e92c8-64bit'.
Done installing SDK 'sdk-releases-upstream-4f68bb2a505c727bcf58195cf4da20592a6e92c8-64bit'.
leooliliu@LEOOLILIU-MB0 emsdk % ./emsdk activate latest
Resolving SDK alias 'latest' to '3.1.26'
Resolving SDK version '3.1.26' to 'sdk-releases-upstream-4f68bb2a505c727bcf58195cf4da20592a6e92c8-64bit'
Setting the following tools as active:
node-14.18.2-64bit
python-3.9.2-64bit
releases-upstream-4f68bb2a505c727bcf58195cf4da20592a6e92c8-64bit
Next steps:
- To conveniently access emsdk tools from the command line,
consider adding the following directories to your PATH:
/Users/leooliliu/tencent/webassembly/emsdk
/Users/leooliliu/tencent/webassembly/emsdk/node/14.18.2_64bit/bin
/Users/leooliliu/tencent/webassembly/emsdk/upstream/emscripten
- This can be done for the current shell by running:
source "/Users/leooliliu/tencent/webassembly/emsdk/emsdk_env.sh"
- Configure emsdk in your shell startup scripts by running:
echo 'source "/Users/leooliliu/tencent/webassembly/emsdk/emsdk_env.sh"' >> $HOME/.zprofile
这些步骤完成以后,安装完成。将 Emscripten 的环境变量配置到当前的命令行窗口下。
代码语言:javascript复制$ source ./emsdk_env.sh
3. 编译第一个程序
现在,一个完整的工具链已经准备好了,可以试着将一个简单的程序编译成 WebAssembly。在此之前,还有一些值得注意的地方:
- 在使用 emcc 命令时,要带着 -s WASM=1 参数(默认将会编译成asm.js)。
- 如果想让 Emscripten 生成一个所写程序的HTML页面,同时带有 wasm 和 JS 文件,我们需要在输出的文件名后加 .html 后缀名。
- 最后,当运行程序时,不能直接在浏览器中打开 HTML 文件,因为跨域请求是不支持 file 协议的。我们需要将我们的输出文件运行在HTTP协议上。
新建一个c文件hello.c,编写一个简单的c程序。
代码语言:javascript复制#include <stdio.h>
int main(int argc, char ** argv) {
printf("Hello, world!");
}
然后使用命令emcc hello.c -s WASM=1 -o hello.html编译该c文件,执行时可能会遇到找不到 emcc 命令的问题。
这需要在emsdk文件夹下执行一下命令:source ./emsdk_env.sh
环境变量设置完成之后,再次执行命令:emcc hello.c -s WASM=1 -o hello.html。无任何提示输出即为执行成功。该操作会在我们本地生成三个文件,分别是: hello.html,hello.js,hello.wasm。
4.运行
我们可以使用emrun来运行生成好的html文件,首先通过命令 emrun --list_browsers 查看一下我们本地支持的浏览器有哪些。
然后可以选择其中某个浏览器用于我们html文件的运行。使用命令 emrun --browser chrome hello.html 选择用chrome来运行html文件。运行后的效果如下:
但是运行之后并没有看到我们的输出内容Hello, world!这是因为 printf 打印时,因为没有刷新缓冲区,没有看到我们的Hello world, 需要增加编译选项:emcc hello.c -o hello.html -s EXIT_RUNTIME=1。执行完成之后再次运行hello.html文件便可看到文字输出。
至此,第一个 WebAssembly 程序则编译成功了!