了解 Emscripten

Emscripten 是什么?

Emscripten 是一个 开源的编译器,可以将 C/C++ 的代码编译后高效运行在现代浏览器上面。Emscripten 的底层是基于 LLVM 编译器的,可以查看其开源的 emscripten llvmemscripten clang

下图是其编译 C/C++ 的代码的流程图:

官网Emscripten 的定义:

Emscripten is a toolchain for compiling to asm.js and WebAssembly, built using LLVM, that lets you run C and C++ on the web at near-native speed without plugins.

截止本文发布,Emscripten 最新版本是 1.38.27.

安装条件

以下是我安装和使用 Emscripten 的条件。

  • macOS 版本 10.14
  • Git,可通过 Homebrew 安装
  • CMake,可通过 Homebrew 安装
  • Xcode 10.1
  • Python 2.7.x,Mac 系统自带
  • 稳定快速的网络环境,最重要和最关键的的是要有(neng)梯(fan)子(qiang)
  • 解决问题的态度和毅力

通过 emsdk 安装

安装 Emscripten 可以通过安装 emscripten SDK 来完成,emscripten SDK 可以简单的理解为是 Emscripten 的一套工具链。

在你自己的电脑上面任意新建一个目录,如我的 ~/dev/emscwork,打开终端,进入此目录。

1、下载 emsdk

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

2、进入 emsdk 目录

1
cd emsdk

3、开始安装

1
2
3
4
5
6
7
8
9
10
11
# Fetch the latest version of the emsdk (not needed the first time you clone)
git pull
# 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
# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh

注意: 每次更新完 emsdk 后,依旧需要执行上面命令重新安装和激活。

另外一个比较常用的是 ./emsdk update-tags 这个命令,可以直接更新 emsdk 的最新 tags 版本,更新 tags 完成后,重新安装和激活最新版的 emsdk 套件。

配置 emsdk

如果你想在任意路径下都可以使用 emsdk 里面的各种工具(就是一些二进制可执行文件),需要为其设置环境变量。

编辑 ~/.bash_profile 文件,新增如下代码:

1
2
3
4
export EMSDK=~/emscwork/emsdk
export EMSCRIPTEN=$EMSDK/emscripten/1.38.27
export BINARYEN_ROOT=$EMSDK/binaryen/master_64bit_binaryen
export PATH=$EMSDK:$EMSCRIPTEN:$BINARYEN_ROOT:$PATH

执行下面命令, 使刚配置的文件生效。

1
source ~/.bash_profile

至此,安装和设置环境变量完成。

可以使用下面命令来查看 emsdk 的安装情况。

1
emcc --version
1
2
3
4
emcc (Emscripten gcc/clang-like replacement) 1.38.27 (commit ea5d631a5446632e195765d89a53ead71cd6de45)
Copyright (C) 2014 the Emscripten authors (see AUTHORS.txt)
This is free and open source software under the MIT license.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

emcc 是一个可执行脚本,该脚本在 emsdk/emscripten/1.38.27 目录下。

1
emcc --help

上面命令可以查看更多关于 emcc 的使用方法.

编译 C/C++ 代码

这里举个实际的例子。

main.c

1
2
3
4
5
6
#include <stdio.h>
int main(int argc, char ** argv)
{
printf("Emscripten show in browser...\n");
}

使用 emcc 编译,如下:

1
emcc main.c -s WASM=1 -o mz.html

这里要注意 WASM=1 这个选项,现在新版 SDK 默认 WASM=1 了,如果不想生成 .wasm 这个文件,需要指定 WASM=0 选项。

生成另外三个文件如下:

1
mz.html mz.js mz.wasm

简单介绍一下这三个文件

1、mz.wasm

二进制的 wasm 模块代码

2、mz.js

胶水代码,包含了原生 C 函数和 JavaScript/wasm 之间转换的 JS 文件

3、mz.html

用来加载、编译和实例化 wasm 代码并且将其输出在浏览器显示上的 HTML 文件

最后执行下面的命令,可以在 Safari 浏览器中显示效果

1
emrun mz.html

main.cpp

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
int main(int argc, char ** argv)
{
cout << "Emscripten show in browser..." << endl;
return 0;
}

编译 C++ 文件(main.cpp)

1
emcc main.cpp -s WASM=1 -o mzcpp.html

同样的方式编译和运行 mzcpp.html 即可看到同样的效果。

Emscripten 应用场景

Emscripten 只是一个编译器,能将我们的高级语言编译为浏览器可以识别并运行的程序,这个看起来确实很诱人。

就目前来说,Emscripten 应用场景可以使用在安全和游戏上面。

1、安全

C/C++ 代码经过编译之后,会生成 wasm 格式 的二进制文件,这个安全级别较高,即使在浏览器中运行,破解者也不会很轻松的破解代码,这样一些在 JS 中涉及到安全的问题,可以使用 C/C++ 来写结合一些加密技术,然后用 Emscripten 编译。

2、游戏

如果能把用 C/C++ 语言写的游戏,转为可在浏览器直接运行的H5游戏,那就很美好了,用户不需要下载游戏,直接玩。现代浏览器技术的更新和发展已经让这个想法变成了现实,至少在主流的浏览器上面。

推荐大家看看这篇文章 JavaScript是如何工作的:与WebAssembly比较及其使用场景

参考文档

About Emscripten

Download and install

编译 C/C++ 为 WebAssembly

WebAssembly 概念


扫码关注,你我就各多一个朋友~

坚持原创技术分享!