|
本サイトは移転しました。旧アドレスからのリダイレクトは2025年03月31日(月)まで有効です。
|
🛈 | ✖ |
ICUライブラリを自分でビルドする手順を説明し、データサイズの縮小方法を示す。
ICUはユニコードによる国際化ライブラリで、本サイトはboostライブラリの導入時に依存ライブラリとしてICUを導入している。標準のICUライブラリは30メガバイト近いデータ(ICUデータ)を必要とするため、機能の一部しか利用しないアプリケーションでは過大となる。これを縮小する最も簡便な方法はオプションを変更してビルドし直す事であり、またデバッグビルドすればライブラリ内部までデバッガ追跡可能となる。本記事はバージョン69.1を前提に記述する。
リンク先からicu-release-69-1.zipをダウンロードする。
ディレクトリは以下とする。異なるバージョンのソースコード展開ディレクトリはICUルートの配下に並列させる。
目的 | ディレクトリ |
---|---|
ICUルート | C:\ICU |
ソースコードの展開 | C:\ICU\icu-release-69-1 |
ビルドの出力 | C:\ICU\icu-release-69-1\icu4c\my_builds\[ビルド名] |
zipファイルをICUルートに置きエクスプローラー右クリック[すべて展開]で[圧縮(ZIP)形式フォルダーの展開]ダイアログ[ファイルを以下のフォルダーに展開する]をC:\ICUに変更して[展開]する。デフォルトのままではicu-release-69-1ディレクトリをルートとして圧縮されているため一階層余分になる。展開ディレクトリはicu4cとicu4jサブディレクトリを持ち、それぞれC言語/C++(ICU4C)とJava(ICU4J)に対応する。従って本サイト作業はicu4c配下で行い、runConfigureICUスクリプトからconfigure(コンフィグレーションスクリプト)を実行してビルドする。本記事での相対パスはicu4c(C:\ICU\icu-release-69-1\icu4c)からとする。
ディレクトリ | ファイル | 内容 |
---|---|---|
C:\ICU | ||
└ icu-release-69-1 | ||
├ icu4c | ||
|├ source | runConfigureICU | configure実行スクリプト |
│││ | configure | コンフィグレーションスクリプト |
│││ | Makefile.in | メイクファイル(Makefile)テンプレート |
│││ | ... | ... |
││├ common | Makefile.in | 共通ライブラリメイクファイルテンプレート |
││││ | *.cpp,*.h | ソースコード、インクルード |
│││└ unicode | *.h | ライブラリインクルード |
│︙︙ | ... | ... |
├ icu4j | ... | ... |
︙ |
本サイトはMSYS2のmingw32/mingw64サブシステムでそれぞれ32ビット/64ビットライブラリをビルドする。ウィンドウズではあるがmingw32/mingw64のPOSIX互換ターミナルで作業しリンクのHow To Build And Install On Unixに準拠する。
runConfigureICUスクリプトで各ディレクトリのメイクファイル(Makefile)やメイク補助ファイル(*.mk)などを作成し、MSYS2のmakeコマンドツールでビルドする。runConfigureICUはプラットフォームを設定してconfigureスクリプトを実行する。
32ビット/64ビットの選択以外はrunConfigureICU、configureオプションで設定し、MinGWプラットフォームとして以下のように実行する。
本サイトのオプション設定は以下に限定するが、設定可能な全オプションはrunConfigureICU --helpおよびconfigure --helpで知ることができる。
runConfigureICUオプション | 機能 | 有 | 無 |
---|---|---|---|
--enable-debug | デバッグ情報生成フラグを加える | 生成する(-g) | 生成しない |
--disable-release | 最適化フラグを加えない | 最適化しない | 最適化する(-O3) |
configureオプション | 機能 | 有 | 無 |
---|---|---|---|
--disable-shared | ダイナミックリンクライブラリをビルドしない | ビルドしない | ビルドする |
--enable-static | スタティックリンクライブラリをビルドする | ビルドする | ビルドしない |
--with-data-packaging | ICUデータパッケージの方法 | 後述 | auto |
バージョン69.1はconfigureオプション--disable-sharedかつ--enable-staticとしてスタティックリンクライブラリのみビルドすると失敗する。ライブラリビルドに続いてICUデータパッケージ構築などのツールをビルドするが、これらがビルド済みライブラリの一つであるツールユーティリティをダイナミックリンクするためである。configureが生成するファイルの一つ(my_builds\[ビルド名]\icudefs.mk)にパッチを当てれば修正できるが思わぬ副作用を招く恐れもあり、スタティックリンクビルドも必ずダイナミックリンクビルドを伴うとして--disable-sharedを使用しないと決めた方が安心だろう。本サイトは常に--enable-staticを与えてスタティックリンクとダイナミックリンク両方のライブラリをビルドする。
configureの--with-data-packagingオプションはICUデータパッケージのビルド方法を指定するが、大きくはライブラリとしてメモリマップするか、データファイルとして読み込むかの二通りに分けられる。本サイト開発環境でautoはlibraryと同じで、デフォルトはダイナミックリンクライブラリとなる。
configureオプション | 機能 | 分類 |
---|---|---|
--with-data-packaging=files | 複数からなる生データファイル | データファイル |
--with-data-packaging=archive | アーカイブした単一のデータファイル | |
--with-data-packaging=library | ダイナミックリンクライブラリ | ライブラリ |
--with-data-packaging=static | スタティックリンクライブラリ | |
--with-data-packaging=auto | 可能ならダイナミックリンクライブラリ(デフォルト) |
データパッケージビルドは他のライブラリビルドから独立であるべきだがライブラリビルドの一部として扱っているため、異なる--with-data-packagingオプション毎に全ライブラリをビルドする事になり効率が悪い。本サイトはこれらを同一ディレクトリでビルドする。ビルド毎にrunConfigureICUは全てのメイクファイルを再作成するが、メイクは不要なコンパイルなどをスキップして重複作業のかなりの部分を省略できる。出力するデータファイルあるいはライブラリファイルが他オプションのそれを上書きする心配は無い。生データファイルは全てのオプションで中間生成されるため、archive、library、staticを順次ビルドすれば全オプションの出力ファイルを得る。
以下に各ビルドのオプションをまとめるが、本当に必要とするものだけをビルドすれば良い。ライブラリはダイナミックリンク、スタティックリンクの両方を作成する。各ビルドは--with-data-packaging=archive、library、staticで3回ビルドして全種類のデータパッケージを得る。
ビルド名 | サブシステム | runConfigureICUオプション | configureオプション |
---|---|---|---|
debug32 | mingw32 | --enable-debug --disable-release | --enable-static --with-data-packaging=[データパッケージ] |
release32 | |||
debug64 | mingw64 | --enable-debug --disable-release | |
release64 |
icu4cディレクトリにmy_buildsディレクトリを作成し、さらに各ビルドの出力ディレクトリを作成する。
configureの作成したMakefileはinstallフォニーターゲットを持つが、これをターゲットとしてメイクする(make install)とmingw32/mingw64サブシステムのinclude/lib/binディレクトリのICUファイルを上書きする。MSYS2はboostライブラリ導入時に依存ライブラリとしてICUを既に導入しており、この上書きは危険な結果を招きかねない。デフォルトターゲットによるメイク(make)でカレント配下への出力に限定してMSYS2導入や他バージョンとの共存を図る。
debug64を例にビルド方法を示す。runConfigureICUに適切なrunConfigureICUオプションとconfigureオプションを与えて実行し、デフォルトターゲットでメイクする。これを--with-data-packaging=archive、library、staticで繰り返すがビルドを3回待つのは苦痛で、その度にオプションをコマンドライン指定しなければならないので、bashスクリプトmy_buildをdebug64ディレクトリに作成して実行する。
filters.jsonはデータパッケージに含むデータを指定する。ここでは空としてデフォルトの全データを含ませるが、常にデフォルトデータのままで良ければ不要でmy_buildのexport行も削除する。なお、filters.jsonによるデータパッケージサイズの削減方法を後述する。
runConfigureICUおよびmakeが出力ディレクトリ(my_builds\debug64)に生成するファイルの配置を示す。runConfigureICUはsourceディレクトリとほぼ同じディレクトリ階層をdebug64ディレクトリに作成し、各ディレクトリにメイクファイルを配置する。ディレクトリのいくつかはメイクファイルの補助ファイルを持つ。例えば...\data\rules.mkは...\filters.jsonから作成したデータパッケージビルド用の補助ファイルで、...\data\Makefileはこれをインクルードする。makeはメイクファイル(my_builds\debug\Makefile)を実行するが、これは主にディレクトリ階層を巡回して各メイクファイルを実行する。
ディレクトリ | ファイル | 内容 |
---|---|---|
C:\ICU | ||
└ icu-release-69-1 | ||
├ icu4c | ||
|├ source | runConfigureICU | configure実行スクリプト |
││︙ | ... | ... |
|├ my_builds | ||
││├ debug64 | my_build | 本サイトが追加したスクリプト |
││││ | filters.json | 本サイトが追加したデータパッケージ設定 |
││││ | Makefile | メイクファイル |
││││ | ... | ... |
│││├ config | ... | (コンフィグディレクトリ) |
│││├ common | Makefile | 共通ライブラリメイクファイル |
││││ | *.d, *.o, *.ao | 依存関係、オブジェクト |
│││├ i18n | ... | (i18nライブラリビルドディレクトリ) |
│││├ layoutex | ... | (レイアウト拡張ライブラリビルドディレクトリ) |
│││├ io | ... | (ユニコードstdioライブラリビルドディレクトリ) |
│││︙ | ||
│││├ tools | Makefile | サブディレクトリ巡回メイクファイル |
││││├ makeconv | Makefile | makeconv(コード変換データ作成)メイクファイル |
│││││ | *.d, *.o, | 依存関係、オブジェクト |
││││︙ | ... | ... |
││││└ toolutils | ... | (ツールユーティリティライブラリビルドディレクトリ) |
│││├ data | Makefile | データパッケージメイクファイル |
│││││ | rules.mk | データパッケージメイク補助、filters.jsonから作成 |
│││││ | ... | ... |
││││└ out | icudt69l.dat | アーカイブデータ |
││││ ├ build | ||
││││ │└ icudt69l | ... | 生データディレクトリ |
││││ ︙ ︙ | ... | ... |
│││├ bin | *.exe | ツール実行、makeconv.exeなど |
│││├ lib | *.dll | ダイナミックリンクライブラリ、icuucd69.dllなど |
││││ | *.dll.a | インポートライブラリ、libicuucd.dll.aなど |
││││ | *.a | スタティックリンクライブラリ、libsicuucd.aなど |
││││ | icudtd69.dll | データダイナミックリンクライブラリ |
││││ | libicudtd.dll.a | データインポートライブラリ |
││││ | libicudtd.a, libsicudtd.a | データスタティックリンクライブラリ |
│││├ stubdata | Makefile | スタブデータライブラリメイクファイル |
││││ | icudtd69.dll | スタブデータダイナミックリンクライブラリ |
││││ | libicudtd.dll.a | スタブデータインポートライブラリ |
││││ | libsicudtd.a | スタブデータスタティックリンクライブラリ |
││││ | ... | ... |
│││├ samples | ... | (サンプル用ビルドディレクトリ) |
│││└ test | ... | (テスト用ビルドディレクトリ) |
││︙ | ... | |
︙︙ |
オブジェクトファイル*.oはダイナミックリンクライブラリビルド用、*.aoはスタティックリンクライブラリビルド用であるが、本サイト環境では両者に差異は無い。データスタティックリンクライブラリlibicudtd.aとlibsicudtd.aも同様で、それぞれダイナミックリンクライブラリあるいはスタティックリンクライブラリのクライアント用であるが、これも差異は無い。デバッグビルドはファイル本体名末尾(バージョン番号を含む場合はバージョン番号の前)に"d"を挿入するが、リリースビルドは挿入しない。mingw32サブシステムビルドはデータスタティックリンクライブラリのファイル名が何らかの不具合でliblibicudtd.aまたはliblibsicudtd.aとなるが、スタブデータのそれはlibsicudtd.aのままなので注意する。生データディレクトリ名末尾、およびアーカイブデータのファイル名末尾の"l"はデータがリトルエンディアンである事を示す。
スタブデータスタティックリンクライブラリはデータを全く含まないデータパッケージである。データパッケージをデータファイルとする場合、データライブラリは不要だが無いとリンクエラーでビルドできないため、代わりにスタブデータライブラリを用いる。なお両者でインポートライブラリlibicudtd.dll.aに差異は無い。
データパッケージを除くライブラリファイルをまとめる。以降、デバッグビルドが追加する"d"は(d)と表記する。これら全て...\libに配置される。
ライブラリ | ダイナミックリンク | インポート | スタティックリンク | 備考 |
---|---|---|---|---|
共通 | icuuc(d)69.dll | libicuuc(d).dll.a | libsicuuc(d).a | |
i18n | icuin(d)69.dll | libicuin(d).dll.a | libsicuin(d).a | |
レイアウト拡張 | iculx(d)69.dll | libiculx(d).dll.a | libsiculx(d).a | |
ユニコードstdio | icuio(d)69.dll | libicuio(d).dll.a | libsicuio(d).a | |
ツールユーティリティ | icutu(d)69.dll | libicutu(d).dll.a | libsicutu(d).a | makeconvなどのツールが利用 |
データパッケージファイルをライブラリ、スタブライブラリも含めてまとめる。
種類 | データパッケージ | ファイル | 配置 | |
---|---|---|---|---|
ライブラリ | ダイナミックリンク | icudt(d)69.dll | ...\lib | |
インポート | libicudt(d).dll.a | |||
スタティック | mingw32 | liblibicudt(d).a, liblibsicudt(d).a | ||
mingw64 | libicudt(d).a, libsicudt(d).a | |||
スタブライブラリ | ダイナミックリンク | icudt(d)69.dll | ...\stubdata | |
インポート | libicudt(d).dll.a | |||
スタティック | libsicudt(d).a | |||
データ | 生データディレクトリ | icudt69l | ...\data\out\build | |
アーカイブ | icudt69l.dat | ...\data\out |
クライアントプロジェクトがビルドしたICUを利用するにはコンパイラ/リンカ探索にMSYS2導入より優先してディレクトリを追加する。本サイトはデフォルトターゲットにとどめmake installしないためライブラリインクルードは展開時の配置を参照しなければならず、ICUではライブラリ毎のディレクトリに分散する。データパッケージをデータファイルとする場合はスタブデータライブラリをリンクする。
種類 | MSYS2より前置するディレクトリ | |
---|---|---|
インクルード | C:\ICU\icu-release-69-1\icu4c\source\common | |
C:\ICU\icu-release-69-1\icu4c\source\i18n | ||
C:\ICU\icu-release-69-1\icu4c\source\layoutex | ||
C:\ICU\icu-release-69-1\icu4c\source\io | ||
ライブラリ | データライブラリ利用 | C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\lib |
データファイル利用 | C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\stubdata | |
C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\lib |
ダイナミックリンクライブラリ(DLL)は...\lib(スタブデータライブラリは...\stubdata)に出力する。これを利用するにはDLLをプログラムと同じディレクトリにコピーするか、あるいは実行パス(環境変数PATH)を通す。
種類 | MSYS2より前置するディレクトリ | |
---|---|---|
実行パス(PATH) | データライブラリ利用 | C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\lib |
データファイル利用 | C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\stubdata | |
C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\lib |
データパッケージの選択優先順位は以下とされる。
データファイル探索のディレクトリ優先順位は以下とされるが、データライブラリを使用するなら関係ない。
以下サンプルコードはUTF-16文字列をシフトJISに変換してコマンドプロンプト出力するもので、データライブラリをリンクすれば正常に動作する。スタブデータライブラリをリンクするとU_FILE_ACCESS_ERRORとなるが、(1)をアンコメントして生データディレクトリを参照、または(2)をアンコメントしてアーカイブデータを参照すれば正常動作する。
runConfigureICUの実行するconfigureスクリプトはsource\pythonディレクトリのPythonモジュールicutools.databuilderを用いてICU_DATA_FILTER_FILE環境変数で指定するデータパッケージ設定ファイル(my_builds\debug64\filters.json)からmy_builds\debug64\data\rules.mkを作成する。...\data\Makefileはこれをインクルードして設定ファイル指定のデータからデータパッケージをビルドする。設定ファイルが無いか空の場合はデフォルトとして全データとなる。データソースはsource\dataに存在する。
文字コード変換だけを利用するとしてデータパッケージサイズを削減する。...\filters.jsonを以下に置き換え、...\my_buildスクリプトを実行してビルドし直す。mingw64でビルドされるデータパッケージサイズを比較するがmingw32もほぼ同様となる。なおicudt69lは生データディレクトリに含まれるファイルサイズ総和を示す。
データ | icudt(d)69.dll | libsicudt(d).a | icudt69l | icudt69l.dat |
---|---|---|---|---|
全データ | 27.43MiB | 27.34MiB | 27.1MiB | 27.34MiB |
文字コード変換のみ | 5.05MiB | 4.96MiB | 4.95MiB | 4.96MiB |
Code::BlocksからMSYS2導入ICUライブラリを利用するための設定と、本記事でビルドしたICUライブラリを利用する設定を示す。サンプル実行やデバッグ確認の方法は省略する。
MSYS2が導入するデータパッケージは全データを含むデータライブラリに限定される。レイアウト拡張ライブラリは導入しない。インクルードファイル、ライブラリファイルは標準ディレクトリに導入されていてライブラリ指定だけを追加する。[Project|Build option]の[Project build options]ダイアログの各ターゲット[Linker setting]ページ[Link libraries]リストボックスに以下を追加するが、もちろん不要なライブラリは省ける。文字コード変換だけなら共通ライブラリとデータライブラリだけで良い。
ダイナミック | スタティック | 説明 |
---|---|---|
libicuuc.dll.a | libicuuc.a | 共通 |
libicuin.dll.a | libicuin.a | i18n |
libicuio.dll.a | libicuio.a | ユニコードstdio |
libicudt.dll.a | libicudt.a | データライブラリ |
本記事でビルドしたデータパッケージはデータライブラリまたはデータファイルでそれぞれ設定は異なる。最初にデータライブラリを用いる場合を説明する。ライブラリ指定として以下を[Link libraries]リストボックスに追加するが、mingw32ビルドlibsicudt(d).aは前置"lib"が重なりliblibsicudt(d).aとなる。デバッグターゲットは(d)に"d"を挿入し、リリースターゲットは挿入しない。
ダイナミック | スタティック | 説明 |
---|---|---|
libicuuc(d).dll.a | libsicuuc(d).a | 共通 |
libicuin(d).dll.a | libsicuin(d).a | i18n |
libicuio(d).dll.a | libsicuio(d).a | ユニコードstdio |
libiculx(d).dll.a | libsiculx(d).a | レイアウト拡張 |
libicudt(d).dll.a | libsicudt(d).a | データライブラリ |
コンパイラ/リンカ探索はビルドICUをMSYS2導入に優先させる。[Project|Build option]で各ターゲット[Search directories]ページの[Compiler]ページ、[Linker]ページの探索パスに以下を追加する。[Compiler]はライブラリ毎に設定する。[Linker]の"debug64"はターゲットに合わせて適切に書き換える。
ページ | 探索パス | 説明 |
---|---|---|
[Compiler] | C:\ICU\icu-release-69-1\icu4c\source\common | 共通 |
C:\ICU\icu-release-69-1\icu4c\source\i18n | i18n | |
C:\ICU\icu-release-69-1\icu4c\source\io | ユニコードstdio | |
C:\ICU\icu-release-69-1\icu4c\source\layoutex | レイアウト拡張 | |
[Linker] | C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\lib | - |
データパッケージにデータファイルを用いる場合は以下となる。こちらのmingw32ビルドlibsicudt(d).aは前置"lib"が重ならない。探索パス[Linker]トップに...\stubdataを追加してスタブデータライブラリをデータライブラリの代わりにリンクする。
ダイナミック | スタティック | 説明 |
---|---|---|
libicuuc(d).dll.a | libsicuuc(d).a | 共通 |
libicuin(d).dll.a | libsicuin(d).a | i18n |
libicuio(d).dll.a | libsicuio(d).a | ユニコードstdio |
libiculx(d).dll.a | libsiculx(d).a | レイアウト拡張 |
libicudt(d).dll.a | libsicudt(d).a | スタブデータライブラリ |
ページ | 探索パス | 説明 |
---|---|---|
[Compiler] | C:\ICU\icu-release-69-1\icu4c\source\common | 共通 |
C:\ICU\icu-release-69-1\icu4c\source\i18n | i18n | |
C:\ICU\icu-release-69-1\icu4c\source\io | ユニコードstdio | |
C:\ICU\icu-release-69-1\icu4c\source\layoutex | レイアウト拡張 | |
[Linker] | C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\stubdata | スタブデータ |
C:\ICU\icu-release-69-1\icu4c\my_builds\debug64\lib | - |