【问题标题】:How to build and use libicu in webassembly如何在 webassembly 中构建和使用 libicu
【发布时间】:2019-05-21 16:01:13
【问题描述】:

我对 JavaScript 项目(在浏览器中)中的 ICU63 库的单词迭代器感兴趣。所以在阅读文档后,我相信ICU默认使用UTF-16,这与JS相同,它可以避免我将JS字符串编码成其他东西。

第一步是用我需要的唯一功能构建一个包装器(我还不知道它是否有效):

#include "emscripten.h"
#include <string.h>
#include <unicode/brkiter.h>
#include <unicode/unistr.h>
#include <unicode/errorcode.h>

using namespace icu_63; 

EMSCRIPTEN_KEEPALIVE
int splitWords(const char *locale, const uint16_t *text, uint16_t *splitted) {
    //Note that Javascript is working in UTF-16
    //icu::
    UnicodeString result = UnicodeString();
    UnicodeString visibleSpace = UnicodeString(" ");
    int32_t previousIdx = 0;
    int32_t idx = -1;

    //Create a Unicode String from input
    UnicodeString uTextArg = UnicodeString(text);
    if (uTextArg.isBogus()) {
        return -1; // input string is bogus
    }

    //Create and init the iterator
    UErrorCode err = U_ZERO_ERROR;
    BreakIterator *iter = BreakIterator::createWordInstance(locale, err);
    if (U_FAILURE(err)) {
        return -2; // cannot build iterator
    }
    iter->setText(uTextArg);

    //Iterate and store results
    while ((idx = iter->next()) != -1) {
        UnicodeString word = UnicodeString(uTextArg, idx, idx - previousIdx);
        result += word;
        result += visibleSpace;
        previousIdx = idx;
    }
    result.trim();
    //The buffer contains UTF-16 characters, so it takes 2 bytes per point
    memcpy(splitted, result.getBuffer(), result.getCapacity() * 2);
    return 0;
}

它可以编译并且看起来不错,只是在尝试链接时缺少符号,因为我不知道如何继续。

LibICU 看起来需要大量内置数据。就我而言,频率表对于使用迭代器这个词是强制性的。

我是否应该尝试将我的包装器复制到源文件夹并尝试弄清楚如何使用 emconfigure。或者当我尝试编译我的包装器时是否可以链接 libicu?第二个选项看起来像浪费数据,因为我对库的大部分不感兴趣。

【问题讨论】:

    标签: icu webassembly


    【解决方案1】:

    根据我的经验,处理库的最简单方法是先使用emconfigure/emmake 构建库,然后将它们与您自己的代码静态链接。像下面这样:

    $ emcc your_wrapper.cpp \
           your_compiled_libICU_static_lib.a \
           -o result.js
    

    使用emconfigure/emmake 编译库有时非常困难,因为您可能需要修改源代码才能使其在 WebAssembly 中工作。

    但是...好消息! Emscripten 提供了一些流行且复杂的库and ICU is one of them 的移植。

    您可以使用-s USE_ICU=1 标志编译您的代码,而无需自己编译 ICU:

    $ emcc your_wrapper.cpp \
           -s USE_ICU=1 \
           -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
           -std=c++11
    

    需要注意的是 Emscripten ICU 端口是 ICU 62。所以你需要将 using namespace icu_63; 更改为 using namespace icu_62;

    【讨论】:

      【解决方案2】:

      虽然-s USE_ICU=1 在您可以轻松修改构建标志时很方便,但我发现从源代码安装 ICU 更方便,因为我还必须构建其他配置/制作/构建过程无法正常运行的库使用-s USE_ICU=1(至少在没有大量修改的情况下并非如此),而是期待一种更传统的方式来查找和链接到 icu 库。

      不幸的是,如果不进行一些调整,构建 libicu 似乎无法与通常的 configure &amp;&amp; make install 一起使用。为此,首先您必须进行“常规”本机构建 (./configure &amp;&amp; make) 以创建必要的本地文件。

      然后,如果您不需要 PTHREADS,您可以按如下相当简单的方式构建,假设 /opt/wasm 是您的 PREFIX。

      PKG_CONFIG_LIBDIR=/opt/wasm/lib/pkgconfig emconfigure ./configure --prefix=/opt/wasm --with-cross-build=`pwd` --enable-static=yes --enable-shared=no --target=wasm32-unknown-emscripten --with-data-packaging=static --enable-icu-config --enable-extras=no --enable-tools=no --enable-samples=no --enable-tests=no
      emmake make clean install
      

      如果您确实需要为 lib 的某些下游使用者提供 PTHREADS,您可能必须从一开始就启用该 lib 来重建 lib。这比较棘手,因为配置脚本在执行需要构建和运行 C sn-ps 的测试时会中断,这是由于有关需要额外节点标志的警告(请参阅https://github.com/emscripten-core/emscripten/issues/15736),这对于configure 脚本意味着错误。我找到的最简单的解决方案是临时修改emcc.py中的make_js_executable

        ...
        with open(script, 'w') as f:
          # f.write('#!%s\n' % cmd); ## replaced with the below line
          f.write('#!%s --experimental-wasm-threads --experimental-wasm-bulk-memory\n' % cmd)
          f.write(src)
        ...
      

      完成该 hack 后,您可以继续执行以下操作(尽管可能,并非所有这些与线程相关的标志都是绝对需要的)

      CXXFLAGS='-s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -O3 -pthread' CFLAGS='-s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -O3 -pthread' FORCE_LIBS='-s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -pthread -lm' PKG_CONFIG_LIBDIR=/opt/wasm/lib/pkgconfig emconfigure ./configure --prefix=/opt/wasm --with-cross-build=`pwd` --enable-static=yes --enable-shared=no --target=wasm32-unknown-emscripten --with-data-packaging=static --enable-icu-config --enable-extras=no --enable-tools=no --enable-samples=no --enable-tests=no
      emmake make clean install
      

      之后,将您的 emcc.py 设置回其原始状态。请注意,如果您尝试构建这些工具,它们将失败——我还没有找到解决方案——但 lib 确实使用上述方法成功安装。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-08
        • 2018-01-24
        • 1970-01-01
        • 2018-10-05
        • 2015-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多