如何使用 emscripten 将 C GNU 科学库 (GSL) 编译为 Web 程序集?

问题描述

目标是将最新的稳定版 GSL 编译为 web assembly 并将其作为 Node.js 模块提供。

我尝试了以下受 this section of the emscripten manual 启发的程序:

git clone git://git.savannah.gnu.org/gsl.git
cd gsl
git checkout tags/release-2-6
autoreconf -i
emconfigure ./configure
emmake make

很遗憾,我收到了多个 wasm-ld: error: duplicate symbol

但是编译 GSL (make) 工作得很好。

我在 Ubuntu 18.04 上使用 emsdk version 2.0.16

有人知道如何解决这个问题吗?

非常感谢您的帮助。

解决方法

终于找到了一个受this gist启发的解决方案。问题与动态链接和共享库有关。

无论如何,以下代码成功将 GSL 编译为 Node.js 模块:

git clone git://git.savannah.gnu.org/gsl.git
cd gsl
git checkout tags/release-2-6
autoreconf -i
emconfigure ./configure

# Note the flag indicating STATIC linking:
# -------------------------======---------
emmake make LDFLAGS=-all-static

emcc -g -O2 -o .libs/gsl.js -s MODULARIZE -s EXPORTED_RUNTIME_METHODS=\[ccall\] -s LINKABLE=1 -s EXPORT_ALL=1  ./.libs/libgsl.a -lm

上面创建了节点模块 ./.libs/gsl.js,它可以在以下示例脚本中使用:

// test_gsl.js

var factory = require('./.libs/gsl.js');

factory().then((instance) => {
  // Compute the value of the Bessel function for x = 5.0:
  var besselRes = instance._gsl_sf_bessel_J0(5.0);
  // Calculate the hypergeometric cumulative probability distribution for:
  // 4: Number of successes (white balls among the taken)
  // 7: Number of white balls in the urn
  // 19: Number of black balls in the urn
  // 13: Number of balls taken
  var hg = instance._gsl_cdf_hypergeometric_P(4,7,19,13);
  // Do the same using `ccall`
  var hg_ccal = instance.ccall("gsl_cdf_hypergeometric_P","number",["number","number" ],[4,13]);
  console.log(`besselRes is: ${besselRes}`);
  console.log(`gsl_cdf_hypergeometric_P(4,13): ${hg}`);
  console.log(`ccall("gsl_cdf_hypergeometric_P",4,13): ${hg_ccal}`);
});

注意在生成的 Node.js 模块中,所有 GSL 函数都以下划线 (_) 为前缀。

上述脚本 (node ./test_gsl.js) 生成此输出:

besselRes is: -0.17759677131433826
gsl_cdf_hypergeometric_P(4,13): 0.8108695652173905
ccall("gsl_cdf_hypergeometric_P",13): 0.8108695652173905

我真诚地希望,这篇文章可以帮助任何人。 祝您玩得愉快,干杯!