Ubuntu24 搭建 Emscripten 环境


1. 准备


安装 cmake, python3 和 git 依赖:

// Install Python
sudo apt-get install python3
// Install CMake (optional, only needed for tests and building Binaryen or LLVM)
sudo apt-get install cmake
// Install git
sudo apt-get install git

2. 安装 Emscripten SDK


从 github 上克隆最新的代码到本地:

// Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git

这里如果你不想用克隆仓库, 也可以直接去 Github 网站上直接下载对应的源代码压缩包即可.

获取到最新的代码之后, 执行以下命令来安装最新的依赖的工具:

// Enter that directory
cd emsdk
// 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

如果一切顺利的话, 安装工作就完成了。

3. Hello World

让我们尝试一个简单的例子, 以确保我们安装的环境能正常工作。

使用 Emscripten 进行编译时有许多选项,但最主要的场景有两个:


3.1 创建 HTML 和相应的 JavaScript 代码


  1. 首先,我们需要一段 c 代码来编译. 例如:
#include <stdio.h>
int main() {
printf("Hello World\n");
return 0;
}
  1. 解析来在命令行中使用 emsdk 来编译上面的代码:
emcc hello.c -o hello.html

-o html.html 是告诉 Emscripten 生成可以运行我们代码的 HTML 页面, 包括 Javscript 胶水语言和 Wasm 模块.

成功执行上述命令之后, 当前目录中的文件应该看起来像这样子:

如何运行该程序

你需要将生成的代码部署到一个 http 服务器上, 然后从一个支持 WebAssembly 的浏览中加载该页面,便可以运行。

不要直接使用本地浏览器打开该 html 文件,这样的话它将不工作,你可能会遇到这个错误: both async and sync fetching of the wasm failed

关于如何搭建一个本地测试 http 服务器,请参考: 如何搭建一个本地测试 http 服务器


3.2 编译 C 代码给 JavaScript 调用


如果你想在 JavaScript 中调用 C 代码中定义的函数,可以使用 Emscripten ccall() 函数和 EMSCRIPTEN_KEEPALIVE 声明,这会将你的函数添加到导出的函数列表中(exported functions)(参考 Why do functions in my C/C++ source code vanish when I compile to WebAssembly).

让我们看看怎么做.

  1. 创建一个新目录,在目录中创建 hello3.c, 内容如下:
#include <stdio.h>
#include <emscripten/emscripten.h>
int main() {
printf("Hello World\n");
return 0;
}
#ifdef __cplusplus
#define EXTERN extern "C"
#else
#define EXTERN
#endif
EXTERN EMSCRIPTEN_KEEPALIVE void myFunction(int argc, char ** argv) {
printf("MyFunction Called\n");
}

默认情况下,Emscripten 生成的代码始终只调用 main 函数,其他函数将作为死代码被删除。将 EMSCRIPTEN_KEEPALIVE 放在函数名称之前可以防止这种情况发生。

这里需要导入 emscripten.h 库才能使用 EMSCRIPTEN_KEEPALIVE

  1. 创建 html_template/shell_minimal.html, 文件内容是 {{{ SCRIPT }}}.
  2. 使用如下命令进行编译。
emcc -o hello3.html hello3.c --shell-file html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1 -s "EXPORTED_RUNTIME_METHODS=['ccall']"

NO_EXIT_RUNTIME=1: 我们需要这个编译选项,否则当 main 函数退出时, runtime 将会被关闭,我们将无法再调用其他方法.

  1. 打开你的 hello3.html 文件,并编辑.
  2. 在第一个 <script type="text/javascript"> 之前添加一个 <button> 元素,如下:
<button id="my-button">Run myFunction</button>
  1. 在第一个 <script> 元素的末尾添加以下代码:
document.getElementById("my-button").addEventListener("click", () => {
alert("check console");
const result = Module.ccall(
"myFunction", // name of C function
null, // return type
null, // argument types
null, // arguments
);
});

上述代码展示了如何使用 ccall 调用 c 语言中到处的方法.

Published at:
July 30, 2025
Keywords:
ui
WebAssembly
javascript
c++
Emscripten
Ubuntu