やや無理矢理な方法を行う必要があるが、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 使って高度な文字コード変換が可能になる。