Edited at

ICU を Emscripten で使う方法

More than 5 years have passed since last update.

やや無理矢理な方法を行う必要があるが、ICU を emscripten 上でもビルドすることが可能である。


1. ホスト環境でビルド

まずクロスビルド環境でビルドする必要が有るため、事前に icu をホスト環境でビルドしておく。ホスト環境は MacOSX とする

mkdir build

cd build
../source/runConfigureICU MacOSX


2. tool 系をいくつか黙らせる

以下のツールは emscripten では正しくビルドできないため、Makefile.in を置換してビルドしないようにする。


  • toolutils

  • genccode

元の Makefile.in は一旦リネームして以下の内容で何もさせないようにする

all:

clean:


3. U_TIMEZONE を書き換える

クロスビルドのために Linux ベースでビルドさせるが、__timezone ではなく emscripten が定義している _timezone に書き換える

@@ -116,7 +116,7 @@

#elif U_PLATFORM == U_PF_ANDROID
# define U_TIMEZONE timezone
#elif U_PLATFORM_IS_LINUX_BASED
-# define U_TIMEZONE __timezone
+# define U_TIMEZONE _timezone
#elif U_PLATFORM_USES_ONLY_WIN32_API
# define U_TIMEZONE _timezone
#elif U_PLATFORM == U_PF_BSD && !defined(__NetBSD__)


4. ビルド

emconfigure と emmake を使ってビルドする

/path/to/emscripten/emconfigure \

../source/configure \
--enable-static \
--disable-shared \
--disable-icuio \
--disable-layout \
--disable-tests \
--disable-samples \
--with-data-packaging=files \
--build=i686-pc-linux-gnu \
--with-cross-build=`pwd`/../build
/path/to/emscripten/emmake make

ビルドしたら lib ディレクトリに libicui18n.a と libicuuc.a があることを確認する。


5. つかう

files で指定しているため、UnicodeString を使用する前にデータを読みこませる必要がある。そのためには icudt[xx].dat を読み出し、udata.h にある udata_setCommonData を使って設定すればよい。

// icudt[xx]l.dat を何らかの方法で読み出し、bytes 変数にメモリ上に配置する

UErrorCode code;
udata_setCommonData(bytes, &code);
if (U_SUCCESS(code)) {
// 読み込みに成功したら UnicodeString を使用する
}
else {
// 読み込みに失敗したらエラー処理を行わせる
}

emscripten には仮想ファイルシステムの仕組みを持っているので、コンパイル時に icudt[xx]l.dat を --embed-file 引数に渡して組み込み、STDIO で読み出して上のコードでやれば JavaScript でも ICU 使って高度な文字コード変換が可能になる。