Open4
mergeable libraryについて
公式ドキュメントや動画
公式以外の資料
WWDC の Meet mergeable libraries
前提知識
- static library
- オブジェクトファイルの集まり
- ビルドタイムに、リンカーは使うAPIを探し、アプリのバイナリにコードをコピーする
- コピーされ、ビルドされたあとは、ライブラリは不要となる
ライブラリの種類 | 特徴 | メリット | デメリット |
---|---|---|---|
スタティックライブラリ | ・オブジェクトファイルの集まり ・ビルドタイムに、リンカーは使うAPIを探し、アプリのバイナリにコードをコピーする |
アプリの起動はダイナミックライブラリよりも早い | ライブラリに変更が入ると、ビルド時間が増える |
ダイナミックライブラリ | ・dylibs ・Xcodeのフレームワークターゲットのバイナリファイル ・フレームワークのコードは実行可能なものにコピーはされず、ライブラリへのパスがアプリのバイナリに記録される ・AppleのSDK以外は、アプリのバンドルにembededされていなければいけない |
ビルドが早い(コードをコピーしていないため) | メモリを消費し、アプリの起動に時間がかかる(dyldと呼ばれるダイナミックリンカーがフレームワークの依存関係を探して、読み込むため) (Appleはこれを考慮した最適化を行っているが、それはアプリに埋め込まれているフレームワークには適用されない) |
参考
mergeable libraries
「Mergeable libraries unlock the best of both linking strategies.」
- 実行可能なものかダイナミックライブラリになりうる
- マージは、スタティックライブラリリンキングに似ている
- 最後に出力されるバイナリは、同じファイルタイプ
新しいスタティックリンカー
-
これがmergeable libraryを可能にしている
-
-make_mergeable
オプションを使用する- リンカーにメタデータの記録を伝える
-
-merge_library
と-merge_framework
オプションを使用する- バイナリが全てのインプットをマージする
-
Xcodeがよしなにやってくれるが、これらはビルドログで確認することができる
-
ライブラリとメタデータは不要なので、マージされたバイナリの大きさのみ気にすれば良い
-
マージされるとき、全てのライブラリを通じたコンテンツの重複排除を行う
-
元々あるオプションや最適化は適用されうる
有効にする方法
- Automatic Merging
- フレームワークターゲットを埋め込んでいる全ての直接的な依存関係をマージする
- アプリターゲットに対して特に役にたつ
- mergeable libraryの出力は、アプリに保存されるため、アプリのサイズやビルド時間に影響が出る
- それを防ぐため、
-no_exported_symbols
- それを防ぐため、
- エントリポイントがApp extensionで必要な場合、export listで定義することもできる
- Manual Merging
-
全てではなく、フレームワークのいくつかをマージしたい場合
-
方法
-
MERGED_BINARY_TYPE
をmanual
にする - マージしたいdylib(ダイナミックライブラリ)を
MERGEABLE_LIBRARY
をYES
にする(ディスクに置いたままにしたければ、NO
にする)
-
-
デバッグモードでは、マージしない
注意点
Autolinking
- デフォルトでオンのオプション
- mergeable libraryからモジュールをインポートしていると、ダイナミックリンキングの問題が発生する可能性がある
- マージされたフレームワークに対してリンクする
- マージされたフレームワークをXcodeのLink Binary With Librariesに追加し、マージされたものは取り除く
- マージされたフレームワークに対してリンクする
- ほとんどのケースでは、ダイナミックリンキングのAPIである
dlopen
は使わないが、必要な場合、パスにマージされたバイナリのパスを定義する必要がある
Runtime APIs
- リソースのlookupもマージの際に影響を受ける
- mergeable librariesを使うには、iOS12以降にアップデートが必要だが、使用しない場合
-Wl, -no_merged_libraries_hook
を使って無効にできる- そうすることでバージョンを上げる必要はなくなる
- mergeable libraryにバンドルリソースを含まない場合も使える
- アプリの起動時間の短縮につながる
Xcode 15のリンカー
- マージは新しいリンカーで有効
- 古いリンカーは広報互換性のために残る
- 新しいリンカーは、armv7k(watchOS8など)のアーキテクチャをサポートしない
フレームワークの配布
- XCFrameworkとしてmergeable libraryを配布する
- クライアントがマージするかどうかを決める
推奨するmergeable libraryへの対処
- マージされたターゲットに対してリンクすること
- Script Phasesでバイナリを使用するツールがある場合、インプットを更新する必要がある
- マージするには、Xcodeのターゲットレベルでで設定する必要がある
- スタティックライブラリをダイナミックライブラリに変更する
- それによってmergeable libraryの対象となりうるから
Mergeable Libraryで高速なアプリ起動を実現しよう!
Deep Dive into Mergeable library