前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebAssembly

WebAssembly

作者头像
QQ音乐技术团队
发布2018-01-31 17:51:04
3.3K1
发布2018-01-31 17:51:04
举报

简介

WebAssembly是由Mozilla、谷歌、微软和苹果共同开发的一种面向Web的二进制格式。该格式名为WebAssembly,可以作为任何编程语言的编译目标,使应用程序可以运行在浏览器或其它代理中。

在WebAssembly之前,这四家公司已经分别自己开发了类似的技术来扩展浏览器的能力,比如微软的typescript、苹果的FLTJIT、谷歌的PNaCI以及Molliza的asm.js。最后这四家公司联起手来搞了个WebAssembly。现在主流的浏览器已经开始尝试支持WebAssembly。 Emscripten编译流程

C/C++  =>  LLVM  =>  Emscripten   =>  asm.js

在编程成LLVM IR的时候编译器会对代码做很多优化,因而能性能上也会有所提升。

可以做什么

通过WebAssembly我们可以把一些C/C++现有的工具或库编译成JS通过浏览器或者Node去执行。比如编译:

  • unreal、unity等游戏引擎
  • FFmpeg等编解码/库
  • SqlLite数据库
  • Python、Lua等运行环境
  • …… 更多场景请访问 Use Case

环境搭建

要使用WebAssembly我们先要安装Emscripten和Binaryen这两套工具,通过Emscripten我们可以把Emscripten编译成asm.js格式的JavaScript,然后通过Binaryen生成最终的WebAssembly二进制文件。

emscripten安装

安装主要有两种方式,一种是通过emsdk来安装,还有一种则是直接通过源码安装。通过emsdk安装只需要通过emsdk install,emsdk activate等几行简单命令安装就会自动完成。如果想理解其中细节最好还是从源码安装,下面以Ubuntu14.04(64位)为例通过源码进行安装。

//首先安装相关依赖
sudo apt-get update
sudo apt-get install python2.7 nodejs build-essential cmake git-core default-jre
//编译Fastcomp,Fastcomp是Emscripten的默认编译器,可以将Clang生成的LLLVM IR编译到JavaScript。
mkdir myfastcomp && cd myfastcomp
git clone https://github.com/kripken/emscripten-fastcomp
cd emscripten-fastcomp
git clone https://github.com/kripken/emscripten-fastcomp-clang tools/clang
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;JSBackend" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DCLANG_INCLUDE_EXAMPLES=OFF -DCLANG_INCLUDE_TESTS=OFF
../configure --enable-optimized --disable-assertions --enable-targets=host,js
make -j2 //-j2根据实际情况分配cpu核数,执行后等待编译即可。
//Fastcomp编译完成后,建立一个目录从git上把emscripten代码拉下来
git clone https://github.com/kripken/emscripten.git
//进入emscripten的目录执行./emcc --help会在当前用户的目录下生成一个.emscripten的文件,里面包含emcc运行的相关配置,这个把LLVM_ROOT的路径指向我们前面编译的Fastcomp的路径,其他配置如果没有特殊需求保持默认就好,LLVM配置如下:
LLVM_ROOT = os.path.expanduser(os.getenv('LLVM') or '/home/vagrant/myfastcomp/emscripten-fastcomp/build/bin') #
//到此安装完成

安装完成后可以通过emcc -v查看相关依赖的配置信息

然后通过编一个最简单的hello来测试下。

#include<stdio.h>
int main(){
        printf("hello\n");
        return 0;
}
vagrant@vagrant-ubuntu-trusty-64:~/wamscode$ ../emscripten/emscripten/emcc hello.c
vagrant@vagrant-ubuntu-trusty-64:~/wamscode$ ls
a.out.js  hello.c
vagrant@vagrant-ubuntu-trusty-64:~/wamscode$ nodejs a.out.js
hello

对于一些大型的开源项目,通常里面提供了自动化编译的脚本。比如通常我们要编译一个开源的C/C++程序我们会执行下面类似的命令。

./configure
make

如果是要编译到WebAssembly的话则需要用emcc去替换掉原来的gcc等编译器,在Emscripten里面已经为我们提供相关脚本方便我们操作。

./emconfigure ./configure
./emmake make
./emcc [-Ox] project.bc -o project.js
Emscripten执行过程

如图所示,emcc使用Clang将C/C++编译成LLVM bitcode,然后通过Fastcomp将bitcode编程成JavaScript,生成的JavaScripit可以在浏览器或者Node环境下执行。

Emscripten运行环境

由于C/C++的执行环境和浏览器不同,编译的时候Emscripten不能只是做下代码的转换,还需要把C/C++的环境也实现。比如:本地运行的C/C++程序可以通过libc或libxx的API去读取本地文件,但是由于浏览器的限制,JavaScript不能再浏览器中读取本地文件,所以Emscripten提供了一个虚拟的文件系统来实现文件读写的需求。

Binaryen

通过Emscripten可以将C/C++的代码编译成Javascript,但还不是最终的WebAssembly二进制文件。通过binaryen我们可以获得最终的二进制文件(.wasm)。

安装
git clone https://github.com/WebAssembly/binaryen.git
cd binaryen
cmake .& make
编译工具

  • asm2wasm : 将asm格式的JavaScript编译成S-表达式的.wast文件
  • wasm-as : 把S-表达式的wast表达式文件编译成最终的WebAssembly二进制文件
在浏览器中运行wasm二进制文件

利用上面的工具我们可以把代码编译成.wasm的二进制文件,接下来用一个简单的例子介绍下WebAssembly二进制文件的编译生成以及在浏览器中的运行。

//my.asm.js
function MyFirstModule(global) {
    "use asm";
    var exp = global.Math.exp;
    function doubleExp(value) {
        value = +value;
        return +(+exp(+value) * 2.0);
    }
    function secondFunc(){
        return +(2);
    }
    return { doubleExp: doubleExp ,secondFunc : secondFunc};
}
//把JavaScript编译成S-表达式
asm2wasm my.asm.js -o my.asm.wast
//my.asm.wast文件内容
(module
  (memory 256 256)
  (export "memory" memory)
  (type $FUNCSIG$dd (func (param f64) (result f64)))
  (import $exp "global.Math" "exp" (param f64) (result f64))
  (export "doubleExp" $doubleExp)
  (export "secondFunc" $secondFunc)
  (func $doubleExp (param $0 f64) (result f64)
    (f64.mul
      (call_import $exp
        (get_local $0)
      )
      (f64.const 2)
    )
  )
  (func $secondFunc (result f64)
    (f64.const 2)
  )
)
把S-表达式编译成二进制的wasm文件
wasm-as my.asm.wast -o my.asm.wasm

生成的wasm二进制文件如下,其中前8个字节成为Preamble,是对整个二进制文件的描述。前四个字字节用来判断是否为有效wasm模块,后面四个字节为wasm的版本。Preamble还有Type section、Function section、Memory section、Export section等,具体的编码细节可参照Binary Encoding

//my.asm.wasm
0061 736d 0b00 0000 0474 7970 658a 8080
8000 0240 0104 0104 4000 0104 0669 6d70
6f72 7492 8080 8000 0100 0b67 6c6f 6261
6c2e 4d61 7468 0365 7870 0866 756e 6374
696f 6e83 8080 8000 0200 0106 6d65 6d6f
7279 8580 8080 0080 0280 0201 0665 7870
6f72 7498 8080 8000 0200 0964 6f75 626c
6545 7870 010a 7365 636f 6e64 4675 6e63
0463 6f64 65a5 8080 8000 0290 8080 8000
0014 0018 0100 1200 0000 0000 0000 408b
8a80 8080 0000 1200 0000 0000 0000 4004
6e61 6d65 9880 8080 0002 0964 6f75 626c
6545 7870 000a 7365 636f 6e64 4675 6e63
00

二进制文件现在得到了,接下我们拿到浏览器里去运行。由于WebAssembly支持的浏览器还少,首先我们需要获得一个支持WebAssembly的浏览器

  • Chrome最新版或者Chrome Canary中启用chrome://flags/#enable-webassembly
  • Microsoft Edge预览版
  • Firefox Nightly中打开about:config设置javascript.options.wasm为true

  • var myFirstModule; fetch("my.asm.wasm") .then(function(response) { return response.arrayBuffer(); }) .then(function(buffer) { var dependencies = { "global": {}, "env": {} }; dependencies["global.Math"] = window.Math; var moduleBufferView = new Uint8Array(buffer); myFirstModule = Wasm.instantiateModule(buffer,dependencies); });
浏览器支持

asm.js:

wasm二进制:

  • Chrome最新版或者Chrome Canary中启用chrome://flags/#enable-webassembly
  • Microsoft Edge预览版
  • Firefox Nightly中打开about:config设置javascript.options.wasm为true

项目示例

videoconvert.js

通过Emscripten把FFmpeg编译成JavaScript,从而实现在浏览器里进行转码。 https://bgrins.github.io/videoconverter.js/

sqllite.js

将C++版本的SqlLite编译成JavaScript,在浏览器中实现数据的功能。https://github.com/kripken/sql.js/

ocrad.js

JavaScript实现图片上的文字库识别。 https://github.com/antimatter15/ocrad.js/

pypy.js

将Python的运行环境编译成JavaScript。http://pypyjs.org/

jslinux

在浏览器器运行linux。 http://bellard.org/jslinux/

Angry Bots

官网上展示一个3D游戏。 https://webassembly.github.io/demo/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-08-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 QQ音乐技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
    • 可以做什么
      • 环境搭建
        • Binaryen
          • 项目示例
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档