Bootstrap

Windows10中Emscripten 安装详解

 

Windows10中Emscripten 安装详解

 

Emscripten编译器,是WebAssembly开发的重要工具之一,主要是通过emcc(Emscripten Compiler Frontend)来工作的。这是个命令行工具。

目前(2020年6月)Windows10中Emscripten 安装比较容易出错,网上文章大多语焉不详,特撰此文,供新手减少挫折感。

 

【WebAssembly?

1,WebAssembly是由 Google、Microsoft、Mozilla、Apple 等几家大公司合作发起的一个关于 面向Web的通用二进制和文本格式 的项目。WebAssembly 是除了 JavaScript 以外,另一种可以在网页中运行的编程语言。

2,WebAssembly(缩写WASM)是一种新的字节码格式。并且被设计为多种编程语言(如C、Rust)目标文件格式,以.wasm 为文件名后缀。WASM通过LLVM(Low Level Virtual Machine、底层虚拟机)工具链支持多种编程语言。

3,WebAssembly初期目标是浏览器内应用程序的高性能执行引擎,随着WASM 在开发者社区中越来越流行,WASM 也正在从客户端迁移到服务端,成为服务端技术的新锐。

 

WebAssembly 可以用 C 语言或者 Rust 开发,再编译成 .was文件(WebAssembly文件),还可以利用TypeScript开发,再编译成 .was文件。

简单地说,WebAssembly 是一种可以使用非 JavaScript 编程语言编写代码并且能在浏览器上运行的技术方案。】

 

一)前提准备

目前的情况(2020年6月),首先要保证你的计算机安装已安装Python 2.7.12或更新版(如2.7.18)和Git。

 

emsdk是一组基于Python 2的脚本,因此首先需要安装Python 2.7.12或更新版(注意2.X系列,而不是3.X系列)。

Python下载地址:https://www.python.org/downloads/

我用的是python-2.7.18.amd64

安装过程一路按默认设置进行即可,最后重启一次电脑。默认安装路径C:\Python27。

 

【特别提示:如果你安装了多个版本Python,请在环境变量中将版本的安装路径放在最前面,参见下图:

 

验证版本:

打开cmd,在提示符>后输入

python –version 回车(即按下Enter键)

参见下图:

如此,则OK。

 

Git

Git是当今最流行的版本控制软件,它包含了许多高级工具。它采用了分布式版本库的作法,不需要服务器端软件,就可以运作版本控制,使得源代码的发布和交流极其方便。后面用到它。

下载地址:https://git-scm.com/downloads

安装过程一路按默认设置进行即可。默认安装路径C:\Program Files\Git。

 

验证版本

Git --version

 

二)安装Emscripten 编译器(emcc)

1、建立安装目录如D:\WebAssemblyTest(根据你的意愿建立)

在cmd中

mkdir d:\WebAssemblyTest

2、克隆emsdk仓库到目录d:\WebAssemblyTest

在cmd中,切换到目录d:\WebAssemblyTest

cd /d d:\WebAssemblyTest

在cmd中输入 git clone https://github.com/juj/emsdk.git ,克隆emsdk仓库,参见下图:

其中,Cloning into 'emsdk'.. 意思是:克隆到“emsdk”。。。

 

3、切换到emsdk文件夹 更新emsdk,确保是最新版

cd emsdk

emsdk.bat update

这里使用的是git,所以运行时会提示使用"git pull"

用一下git pull

 

4、安装,注意这一步比较容易出问题,请保持耐心。对这一步,建议新手先看完整,再进行实践

在cmd中运行emsdk.bat install latest

经验证,这一步一般进行不下去,自动下载安装期间几乎百分百出错:

Error: Downloading URL '…node-v12.9.1-win-x64.zip…': <urlopen error [Errno 10060] >

Installation failed!

 

解决办法:

根据提示,将上网搜索下载需要的.zip文件,放入emsdk目录中的zips目录

再次运行emsdk.bat install latest

我在测试时发现,在git bush中运行emsdk.py install latest,比在cmd中运行emsdk.bat install latest,建议使用git bush,下面演示就是用它。

使用git bush打开git控制台窗口,参见下图:

其中$是git bush的提示符,在提示符后输入

d:/WebAssemblyTest/emsdk/emsdk.py install latest 回车(即按下Enter键)

注意,其中emsdk.py必须带后缀.py 前面的路径根据你的实际情况而定。

如果你已切换到d:/WebAssemblyTest/emsdk路径,命令前的路径就不需要了,可在$提示符后输入emsdk.py install latest 回车(即按下Enter键)

【提示:在git bush中和在cmd中,切换到其他盘符的cd命令,不同之处:

cmd中需要/d,如cd /d d:/WebAssemblyTest/emsdk

git bush中不需要/d,如cd d:/WebAssemblyTest/emsdk 】

 

在安装过程中如果下载报错提示如:

Installing tool 'java-8.152-64bit'..

Error: Downloading URL 'https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/portable_jre_8_update_152_64bit.zip': <urlopen error [Errno 10060] >

Installation failed!

 

注意其中的portable_jre_8_update_152_64bit.zip,你可到网上下载之

看emsdk目录中是否有zips目录若无可手动建立,将上网搜索下载的portable_jre_8_update_152_64bit.zip放入zips目录中(不用解压)。

关闭git bush,重新打开,在$提示符后再次输入

d:/WebAssemblyTest/emsdk/emsdk.py install latest

请耐心等待

已安装好的会自动跳过,参见下图:

请耐心等待一段时间。每次下载报错一次就用重复一次,直至成功完成,参见下图:

 

5、激活sdk包

在git bush中(也可以在cmd中),输入

d:/WebAssemblyTest/emsdk/emsdk.py activate latest

提示:前面的路径根据你的实际情况而定。

请耐心等待完成,参见下图:

 

6、设置环境变量

在cmd中,如下输入,:

d:/WebAssemblyTest/emsdk/emsdk_env.bat

提示:前面的路径根据你的实际情况而定。

参见下图:

提示、你可以手动配置环境变量,在系统变量path中加上(上图PATH +=后面的部分),否则每次打开cmd窗口使用emcc都要运行一次d:/WebAssemblyTest/emsdk/emsdk_env.bat

 

7、验证

emcc -v不报错就成功了,参见下图:

 

获取帮助

emcc --help

 

 

例子

建立一个名为文件hello_world.c ,内容如下:

#include <stdio.h>

int main(int argc, char ** argv) {

  printf("Hello World\n");

}

 

保存到D:\WebAssemblyTest中

 

编译命令简要格式:

emcc c_file -o out_file

其中emcc就是Emscripten编译器行命令,c_file 如test.c是我们的输入文件,使用-o选项可以指定输出文件,out_file 如test.wasm、test.js、test.html,是我们的输出文件。

关于out_file 注意两点:1)out_file可以带路径。2)若为-o test.wasm,则只生成test.wasm这个文件;若为-o test.js,则生成test.js文件 ,还有test.wasm;若为-o test.html,则生成test.html文件,还有test.js和test.wasm。

 

编译上面的例子

在cmd中输入emcc D:\WebAssemblyTest\hello_world.c -s WASM=1 -o D:\WebAssemblyTest\hello_world.html

参见下图:

编译结果是这样的:

 

注意、hello_world.html不能用浏览器直接打开,否则报错,需要先启动http服务。

启动http服务命令

在cmd中输入emrun --no_browser --port 8080 D:\WebAssemblyTest\hello_world.html

注意后面要加参数为具体的hello_world.html文件路径,参见下图:

 

然后启动edge浏览器,在地址栏输入

http://localhost:8080/test.html

访问结果是这样的:

再看看浏览器控制台的输出:

 

再举一例

①建立一个名为文件test.c ,内容如下:

char* toChar (char* str) {

       return str;

}

int add (int x, int y) {

  return x + y;

}

int square (int x) {

  return x * x;

}

 

保存到D:\WebAssemblyTest中

 

②设置环境变量

cmd窗口运行d:/WebAssemblyTest/emsdk/emsdk_env.bat

提示:前面的路径根据你的实际情况而定。

 

③编译上面的例子

在cmd中输入

emcc D:\WebAssemblyTest\test.c -Os -s WASM=1 -s SIDE_MODULE=1 -o D:\WebAssemblyTest\test.wasm

注意、本例和前例不同,使用了优化选项,并仅输出.wasm文件(这里是test.wasm)。

 

④新建test.html加入调用上面产生的test.wasm:

<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8">

  <title>Document</title>

</head>

<body>

 

<script>

  /**

   * @param {String} path wasm 文件路径

   * @param {Object} imports 传递到 wasm 代码中的变量

   */

  function loadWebAssembly (path, imports = {}) {

    return fetch(path) // 加载文件

            .then(response => response.arrayBuffer()) // 转成 ArrayBuffer

            .then(buffer => WebAssembly.compile(buffer))

            .then(module => {

              imports.env = imports.env || {}

 

              // 开辟内存空间

              imports.env.memoryBase = imports.env.memoryBase || 0

              if (!imports.env.memory) {

                imports.env.memory = new WebAssembly.Memory({ initial: 256 })

              }

 

              // 创建变量映射表

              imports.env.tableBase = imports.env.tableBase || 0

              if (!imports.env.table) {

                // 在 MVP 版本中 element 只能是 "anyfunc"

                imports.env.table = new WebAssembly.Table({ initial: 0, element: 'anyfunc' })

              }

 

              // 创建 WebAssembly 实例

              return new WebAssembly.Instance(module, imports)

            })

  }

  // 加载wasm文件

  loadWebAssembly('test.wasm')

          .then(instance => {

            //调用c里面的方法

            const toChar = instance.exports.toChar

            const add = instance.exports.add

            const square = instance.exports.square

           

            console.log('return:   ', toChar("12352324"))

            console.log('10 + 20 =', add(10, 20))

            console.log('3*3 =', square(3))

            console.log('(2 + 5)*2 =', square(add(2 + 5)))

          })

 

</script>

</body>

</html>

 

注意,将test.html放在test.wasm所在目录中。不要用浏览器直接打开test.html,要按下面的介绍进行。

 

⑤启动http服务

emrun --no_browser --port 8080 D:\WebAssemblyTest\test.html

参见下图:

 

⑥然后启动edge浏览器,在地址栏输入

http://localhost:8080/test.html

访问结果是这样的:

 

 

学习资源

WebAssembly编程

https://www.cntofu.com/book/150/index.html

 

 

;