在Windows10搭建WebAssembly开发环境


最近研究WebAssembly技术,准备用WebAssembly编译C/C++代码供前端调用。网上看了很多文章,收获很大,现在就遇到的问题做一个记录。

官网关于windows开发环境搭建基本上几句话,写的太简单,看来是把每个人都当资深程序员了。

https://emscripten.org/docs/getting_started/downloads.html

 

初学者估计会看的一脸懵。网上找了很多文章,都没有特别详细的操作步骤。由于命令行用的不熟,再加上有些文章说用命令安装,数据源来自谷歌,如果没有代理的话可能会下载失败。因此我一开始没有使用官方推荐的方法,而是找了一篇文章,下载了文章中附件emsdk-1.35.0-full-64bit.exe的安装包,安装后点击emsdk_env.bat会自动配置环境变量,永久生效。编写的一个Hello world的C文件也成功编译成了如下图所列的文件:

emcc hello.c -s WASM=1 -o hello.html

 

 

 

 这个安装版的emsdk可以在任意目录先打开cmd执行编译,因为它已经配置了永久生效的系统环境变量。

 直接双击打开hello.html,能正常显示:

 

 

由于我的目标是编译C/C++生成wasm文件,再引入到前端,供js调用C/C++里面的方法,因此当我再编译一个包含自定义加法和乘法的math.c的C文件在前端调用时,代码一直报错找不到这个wasm文件,我确认引入wasm文件路径没有问题,因为反复尝试了十几遍,都是报错404找不到这个math.wasm。此时我就开始怀疑安装的这个emsdk有问题。

因为官网上最新版本编译hello.c文件生成是这样的:

 

 和我自己生成的明显不一样:

因此我下定决心,把刚安装的emsdk1.35.0卸载了,重新按照官网的步骤安装最新版试试。

由于我第一次用安装文件安装时,它会默认安装在C盘,因此环境变量是自动配置C盘路径,卸载时环境变量一起被自动清除了。

1、依据官网步骤,首先安装Git(我很早已经安装了),略过。

2、安装windows CMake

3、安装python

4、在电脑的其他盘,我的在D盘,创建一个目录D:\devEnv\webAssembly。

5、在webAssembly目录下cmd窗口执行下面命令:

 

 

     git clone https://github.com/juj/emsdk.git

     这个从github上下载很快,1分钟搞定。

6、进入下载好的emsdk目录,继续cmd安装最新版本(这一步就是从谷歌的一个地址下载文件,我尝试了很多遍,一开始执行emsdk install  latest报无法连接服务器,1060等错误,试了半天都不行,最后用下面这行命令终于成功了)

emsdk install --global latest

7、当安装完成配置好后执行激活:

emsdk activate latest


8、配置激活后需要应用环境变量(该步操作在每次打开新的cmd窗口时都需要执行emsdk_env.bat,相当于临时配置。手动永久配置到系统的环境变量里我还没尝试)

emsdk_env.bat


9、验证是否安装成功

emcc -v 不会报错
emcc --clear-cache 不会报错


注意:由于我没有手动配置系统环境变量,以上命令操作只能在D:\devEnv\webAssembly\emsdk下执行,其他任何地方执行都会报命令找不到,而且编译C/C++文件也要在这个目录下编译,因为D:\devEnv\webAssembly\emsdk就是编译环境。

 

 

 

 

至此安装完成。可以再尝试编译hello.c生成的文件如下,和官网一致。此时不能直接双击打开了,需要一个本地服务器来访问hello.html。

继续编译math.c,生成math.wasm。在前端调用math.wasm中的加法和乘法。

 

 

安装http服务器 npm install -g serve

cmd启动http服务命令: serve .

浏览器访问自己写的工程目录index.html

 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>
<div id="devTarget" />
</h1>
<script>
/**
* @param {String} path wasm 文件路径
* @param {Object} imports 传递到 wasm 代码中的变量
*/
function loadWebAssembly (path, imports = {}) {
return fetch(path)
.then(response => response.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);
})
}
//调用
loadWebAssembly('./math.wasm')
.then(instance => {
const add = instance.exports.add; //取出c里面的方法
const square = instance.exports.square; //取出c里面的方法
let span = document.createElement('span');
let htmlStr = '10 + 20 = ' + add(10, 20);
htmlStr += '; 3 * 3 = ' + square(3);
span.innerHTML = htmlStr;
let div = document.getElementById('devTarget');
div.appendChild(span);

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>

其中index.html中调用math.wasm中的加法和乘法,在页面显示出

 

 

http://localhost:5000/Desktop/math/

 

 参考文章链接:

https://www.cnblogs.com/jixiaohua/p/10424941.html

https://blog.csdn.net/wangx893175022/article/details/106209322/

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM