ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
統合可能なライブラリの説明
統合可能なライブラリが静的ライブラリと動的ライブラリの優れた部分をどのように組み合わせ、アプリの生産性と実行時のパフォーマンスを向上させるかを説明します。最小のアプリをリリースしながら、より速い開発を可能にする方法を学んでください。またXcode 15で統合可能なライブラリを採用する方法を紹介し、あなたのコードで作業するためのベストプラクティスを紹介します。
関連する章
- 0:55 - Static and dynamic libraries overview
- 1:45 - Meet mergeable libraries
- 5:41 - Benefits of mergeable libraries
- 9:01 - Automatic merging in Xcode
- 13:03 - Manual merging in Xcode
- 16:40 - Debug mode
- 19:07 - Considerations
- 23:59 - Recommendations
- 25:11 - Wrap-up
リソース
関連ビデオ
WWDC22
-
ダウンロード
♪ ♪
シンディです 言語チームのコンパイラエンジニアです マージ可能なライブラリについてご紹介します これはライブラリを構築する 新しいモデルで 静的リンカーを利用します ライブラリのマージで ビルドと実行を高速化
Xcode 15での マージの有効化についても 説明します ライブラリのマージに際し 注意点についても ご紹介します まずは静的なライブラリと 動的ライブラリの違いについて 説明します これによりマージ可能なものの利点が 明らかになります 静的ライブラリは オブジェクトの集合 ビルド時に静的リンクで APIを検索 バイナリに コードをコピーします
コピー後ライブラリは ビルドには不要です 静的ライブラリに 変更が加えられた場合 ビルドに時間がかかります これはアーカイブや リンク方法次第で ビルドやデバッグの遅延が 発生します 動的ライブラリは これを解決します 動的ライブラリは通常 dylibsと呼ばれます Xcodeターゲットの バイナリファイル形式です
このコードは実行可能ファイルに コピーされません 代わりに静的リンクが バイナリに インストールされます Apple SDK以外の フレームワークでは バンドルへの埋め込みが 必須となります 動的ライブラリ変更時の 挙動の違いは 静的リンクへのコードの コピーが不要な点で ビルドが高速化されます ただしランタイムでの使用が 複雑化します そこに動的リンクの登場です 起動時にdyldという動的リンクが 必要なプロパティを チェックします フレームワークに依存する ライブラリも同様です
この数が増えるに従い メモリ使用率や 起動時間に影響します またApple SDKの プロパティを考慮すると 多数のフレームワークが ロードされることもあります その対処のための最適化された ライブラリを用意 埋め込みフレームワークは 対象外です 従って静的でも動的でも ライブラリ使用時には 注意が必要です
動的ライブラリはすぐに ビルドできますが 起動に必要な時間や ビルド時間を考慮すると 静的ライブラリは 時間がかかることもあり得ます そのため開発には 最適の環境整備を 以前はお勧めしてきました マージ可能なライブラリなら その心配は無用です マージ可能ライブラリは リンク戦略をアンロックします パフォーマンスと開発の 最適化について このあと説明します 例えば実行可能ファイルのような バイナリイメージについてかんがえてみましょう このフレームワークのバイナリは 静的リンクに左右されます この相互依存がマージ可能 ライブラリを構成します リンクされた出力がマージ されたバイナリになるのです マージ可能なこれらの依存は 何がつくるのでしょうか? それはどうビルドされたかで 説明できます 動的ライブラリはすべて マージ可能として作られます 静的リンクがライブラリを 作成した場合は 同時にメタデータを生成します メタデータはバイナリ内にあり 全体のサイズが大きくなります リンク依存として利用された時 リンカーはライブラリを静的ライブラリと 同様に扱えるようになります メタデータにより ユーザーはライブラリを 通常の動的ライブラリとして 静的にリンク あるいはマージできます マージしたバイナリは アプリとして使用したり フレームワークのような 動的ライブラリにもできます マージは静的ライブラリの リンク方法にも類似します ライブラリのセグメントを含む バイナリが残ります 出力バイナリは同じ ファイルタイプのままです マージはXcode 15の新機能です 新しく実装された静的リンカーが これを可能にします 新しいリンカーオプションを 使用することで機能します まずマージするライブラリは -make_mergeableでビルドします これによりリンカーにメタデータを 記録するように指示します 次にマージされたバイナリに対して リンカーはそのメタデータを ライブラリとともに出力 その際-merge_libraryまたは -merge_frameworkを使用してください Xcodeはこれらの詳細を 自動的に処理します ビルドログを精査すると これらのオプションが 適用されていることがわかります マージは単にリンクするよりも どの点で優れているのでしょうか マージ後のサイズを 考えてみます まずライブラリと そのメタデータが不要で マージ後に削除することも できます すなわち唯一の焦点は マージされたバイナリのサイズのみ マージ時にリンカーは コンテンツの重複を排除できます ライブラリにわたる文字列なども 含みます たとえば冗長なシンボル 参照を削除します Objective-Cセレクタと objc_msgsendスタブなどです これによりアプリバンドル 全体を小さくできます 最終的なバイナリの イメージ タイプも変わりません すでにサポートされているリンカーの 最適化を適用できるということです これはアプリの起動にも 利点となります ロードされるフレームワークが 少なくなると アプリ起動時にカーネルの 実行必要作業を減らせます メモリ使用量も削減され ユーザーの満足度もアップするでしょう 効果的な開発と メンテナンスには コードをライブラリに分割 することが不可欠です マージ可能ライブラリを使用すると それらを両立することが可能です マージ可能ライブラリの使用で 最小限のコードと構成の変更が 可能になります また新しいフレームワークの採用につれて 適切に拡張されます 動的リンクに関する前の図を もう一度見てみましょう リンカーはメタデータを 生成できるため 埋め込みフレームワークは すべてマージ可能になります 他のライブラリのコンテンツを マージするフレームワークも作成可能です これで埋め込むフレームワークは 1つだけになります 埋め込まれたフレームワーク全体において Dyldはすべてのセグメントを含む1つの ライブラリをロードするだけで済みます この方法でマージすると 依存関係チェーンを大幅に簡素化 これがマージ可能なライブラリで 実現できることです 有効化する方法について 説明します Xcodeでライブラリのマージを 有効化する方法は2つあります 最も単純な自動マージから始めます 次に何をマージ可能にするかを 制御したい場合に備えて 手動マージについても説明します マージ可能なライブラリが 最適なビルド時間をデバッグモードで 提供できることについても説明します それからマージ可能ライブラリを デバッグした後の シンボリケート時の心構えなども ご紹介します 自動マージは組み込みフレーム ワークのターゲットである 全依存関係をマージするように ビルドシステムに通知します これはアプリターゲットで 特に有用です 例を挙げます 例としてSwift および C++ Forest プロジェクトを使用します 4つのフレームワークに リンクするアプリターゲット Apple SDKに含まれる SwiftUI があります 他の3つはForestBuilderと ForestUIおよびForestは プロジェクト内にビルドされてます 自動結合を有効にすると 3つのフォレストのフレームワークが マージ可能なります SwiftUIはシステムライブラリ なのでそのままです アプリをリンクすると これらのフレームワークは アプリのバイナリに 直接マージされます これはフレームワークが 起動時に必要ではなく ディスクから削除できるということです Xcodeでこれをオンにする 方法を見てみましょう
プロジェクトのSwiftおよびC++ ターゲットがクリックされ アプリのビルド設定タブ内にあります MERGED_BINARY_TYPE ビルド設定を更新します フィルター・テキストボックスを 使用して検索
「Create Merged Binary」が ここで更新したいものです これはMERGED_BINARY_TYPE 設定にマップされるオプションです 設定をクリックして その値を“自動”に更新します することはそれだけです!
マージ可能ライブラリの設定は オプションの下です 独自のセクションに 表示されるので便利です 「Linking - Mergeable Libraries」 という名称です アプリでライブラリのマージが 有効になっている場合 ライブラリのセグメントは アプリのバイナリに直接リンク これにより静的ライブラリと 同様のパフォーマンスが得られます マージ可能なライブラリのエクスポートは アプリ内に保存されます ただし多くの場合 アプリがシンボルを エクスポートすることは適用されず サイズとビルド時間に 悪影響を及ぼします これを防ぐには -no_exported_symbols 他のフラグを更新することで Xcodeに適用 -Wl、-no_exported_symbolsを 使用します アプリに拡張機能の エントリ ポイントが必要な場合は 制御にシンボルをリストする エクスポートリストを使用しましょう エクスポートされた シンボルファイルを使用する 一般リンクオプションのなかで 設定できます これで静的リンカーを デッドコードの除去などの サイズの最適化にも 最も効果的にすることができます これが自動マージについてでしたが フレームワークの一部のみを マージする場合もあるでしょう Xcodeは手動マージを 通じてこれをサポートします 手動マージはマージするライブラリを 指定する細かいアプローチです これは一部の依存関係をアプリ バンドルに残す場合に便利です これについては後ほど 詳しく説明します これは包括的なターゲットで MERGED_BINARY_TYPE = manualを 設定することで有効になります 最終的なマージされた製品を 構成するライブラリは MERGEABLE_LIBRARYを YESに設定することで認識されます またディスク上に残しておきたい ライブラリについては MERGEABLE_LIBRARYの デフォルト設定をNOのままにします SwiftとC++ Forestプロジェクトに 戻ってデモンストレーションします 自動マージに関連する変更を 加えずに新たに開始します アプリのターゲットとそれがリンクする 4つのフレームワークがまだ存在します でも現段階ではテストも考えています プロジェクトにはXCTestターゲットと サポート フレームワークがあります テストはフォレストのフレーム ワークにも依存します プロジェクトのフレームワーク間では 依存関係がすべて絡み合っています この例ではXCTestターゲットが ありますが プロジェクトにはアプリ拡張機能などの ターゲットが存在する可能性があり 同様の依存関係グラフが 生成されることもあります
マージ可能ライブラリを 活用するには 3つのフォレストのフレームワークの アプリの依存関係を分離します
ライブラリをマージするフレームワーク ForestKitを作成しますが テストの依存関係も満たす 必要があります
ForestKitはアプリとテストの両方が 依存するイブラリをカプセル化するため グループライブラリと みなされます
手動モードを有効にしているので どのフレームワークをマージ可能に するかを明示的に設定します この場合それはForestBuilderと ForestUIおよびForestです
これらの依存関係は ForestKitにマージされます ロードするライブラリを減らすことで アプリの起動時間とバンドル サイズが改善されました Xcodeでこれを オンにしてみましょう
プロジェクトを再起動して 自動マージ設定をすべて削除し まず他のフレームワークをマージする ターゲットを作成します グループライブラリの ForestKitです 実行には「Target」セクションの 下部をクリックします
テンプレートポップアップの 「macOS」タブにいて フィルタテキストボックスで テンプレートを見つけます
製品名をForestKitに設定して “Finish”をクリックします
このフレームワークでは Forest Test Supportを除く すべてのライブラリを マージしたいと考えています 依存関係が絡み合っているため とりあえず全部リンクしておきます これを行うには 「Link Binarywith Libraries」 ビルドフェーズを更新して プラス記号でフレームワークを追加します
ライブラリのポップアップが表示されたら フォレストフレームワークをクリック SHIFTとDOWN キーを押したままにしてXcode プロジェクト内の他のフレームワークを強調表示
次にこのターゲットで手動マージを 有効化します これはBuild Settingタブに移動し 「Create Merged Binary」を 再検索します フィルター・テキストボックスで 「MERGE」と入力します
今回は値として「Manual」を 選択します グループ・ライブラリ・ターゲットに 設定するのはこれだけです 各フレームワーク・ターゲットの Build Settingに移動して マージするライブラリを 選択できます ターゲットセクションに移動して、 フォレストフレームワークから始めます Build Settingタブ表示後 「マージ可能なライブラリ」をクリックできます このオプションはビルド設定 MERGEABLE_LIBRARYに マップされており 値をYesに更新します
ForestUIとForest Builderに ついても同じ作業です
マージされたForestKit フレームワークが作成されました まだいくつかの依存関係を 更新する必要があります 動的ライブラリをカプセル化する フレームワークを作成したため アプリとテストがForestKitに対して リンクされていることを確認します まず「Swift and C++ App Target」を クリックしてアプリを修正しましょう
Build Phasesタブに戻り 「LinkBinary with Libraries」に進みます ここで不要なフレームワークを 削除します Forestを選択してShiftキーと UPキーを押しながら ForestUIとForestBuilderを 収集して削除します 最後のステップはテストです XCTestターゲットをクリックし 「Link Binary with Libraries」下の Build Phasesタブに移動します
表内の名称をクリックして削除し フォレストフレームワークを 削除します
次にプラス記号を使用して ForestKitを追加します
ポップアップが表示されたら ForestKitをダブルクリック
これが手動マージの設定方法です SwiftおよびC++ Forestプロジェクトでは リリース モードで作業してきました これはライブラリがマージされた後 ディスクから削除されるときです ただしマージにはビルド時間の オーバーヘッドがあり 開発コストが高くなる 可能性があるのは 静的ライブラリのビルド時の 動作と同様です
Xcodeでの反復開発サポートのため リンカーはデバッグモードではマージ不可です ビルドシステムは代わりにライブラリを 再エクスポートするようにリンカーに指示します 再エクスポートはコードの実装を 1つの動的ライブラリ内で 実行できるようにする リンカーオプションで 別のものに実装されている かのようにできます これはマージされたターゲットに 依存するだけで 全ライブラリのAPIに 到達できることを意味しますが それはアプリの拡張機能や テストなどのことです これにより動的ライブラリと同様の ビルド時間の利点が得られます 起動時にdyldはマージされた バイナリから参照が直接取得されるのではなく 再エクスポートされたライブラリへの 参照をリダイレクトします これはデバッグの際マージ可能なライブラリが ディスク上に残ることを意味します
デバッグについて言えば マージ可能なライブラリに含まれる シンボルを調べてみることに します 整数を受け取り その二乗した 結果を返す関数があります これはビルドされるコードです ただしこれはマシンが実行する コードではないことはわかっています 代わりにこのコードは多くの 変換を経ることになります コードにバグがないか調べる必要が あるまではこれで問題ありません これがXcodeがシンボリケーションを サポートする理由です シンボリケーションは これらの命令を元のソースコードに 関連付けるプロセスです これはクラッシュログを 理解したり プロファイリングとデバッグに 役立ちます マージされたバイナリでは どのように機能するでしょうか
マージを有効にしても ソースの場所情報は 元のライブラリから引き続き 保持されます つまりデバッグエクスペリエンスは 変わりません ただしスタックトレースなどの ライブラリ情報が表示される場合は マージされたバイナリへのパスが 表示されることに注意してください この情報はクラッシュログや Instruments内 およびデバッガーに表示されます 独自のプロジェクトでマージ可能な ライブラリをどのように採用できるか 多くの場合それらを有効にするには、 いくつかのXcode設定が必要です それには注目に値する要素も いくつかあります 考える上で重要な5つのトピックに ついて説明します まず既存のマージ可能なライブラリの 依存関係を どう処理するかについて説明します 次に自動リンクとは何かという点と マージ可能なライブラリでの機能について ランタイム ルックアップAPIを 使用する際の いくつかの制限について またdlopenや バンドルインターフェイスなどに ついて触れます マージはXcode 15の静的リンカーに よって強化されているため 前バージョンとの重要な違いに ついても触れておきます そして最後の考慮事項は フレームワークを 他のデベロッパに配布することに 興味がある人向けです
ライブラリの依存関係について dyldの動作図に戻ります マージ可能ライブラリの 依存関係がある場合 他の実行可能ファイルなど マージされていないものは マージ可能なフレームワークは ディスクから削除されるため マージされたフレームワークに 依存するよう更新する必要があります これが起こるもう1つの要因は、 アプリが自動リンクに依存する場合です 自動リンクはデフォルトで オンになっているコンパイラオプションです コンパイラがソースコード内で モジュールのインポートを検出すると フレームワークの依存関係を 検出してリンカーに渡します したがってマージ可能なライブラリから モジュールをインポートする場合は これにより動的リンクに不具合が 発生する可能性があります でも自動リンクを無効に する必要はありません ここでの解決策は以前と同様 マージされたフレームワークにリンクです
これを行う最も一般的な方法は 「Link Binary with Libraries」 Build Phaseでマージされたフレーム ワークを追加することで マージ可能なものが 既に存在する場合は削除します そうしないとdyldはアプリに適切な フレームワークをロードできなくなります
ほとんどのデベロッパはdlopenのような 動的リンクAPI を使用する必要はありません 必要な場合の入力パスは マージされたフレームワーク ターゲットも指す必要があります
同様にリソースの検索はライブラリの マージによって影響を受ける可能性もあります これはランタイムが期待している 挙動だからです Swiftでのバンドルはランタイムに フレームワークのバンドルをロードさせるためのAPIです Objective-Cにおける同等のAPIは NSBundleのBundleForClassです これらのAPIはバンドルの構造を 考慮することなく フレームワークのリソースを 操作するために使用されます
iOS 12まではランタイムは バンドルを検出するために フレームワークのバイナリを 必要としていましたが マージ可能なフレームワークには プロセスが実行されるまでに バイナリが含まれません でも朗報です! iOS 12 では検索を可能にする フックが追加されました そこでバンドル検索サポートに 依存している場合は 最小展開バージョンを更新する 必要があるので マージ可能ライブラリを使用するには iOS 12以降にアップグレードを ただしこれらAPIに依存しない場合は このサポートを無効にできます その際は新しいリンカー オプション -no_merged_libraries_hook を使用します これでアプリの展開バージョンを 更新する必要がなくなります バンドル リソースを含まないフレーム ワークをマージする場合は バンドル フックも必要ない 場合があります この場合起動時のパフォーマンスを 向上させるために このオプションを追加することを 検討してください このセッションを通じて いくつかの新しい リンカーオプションについて言及してきました これらのオプションは新しく実装された リンカーでのみ機能します ツールチェーンの中を覗いてみると 2つの静的リンカーがあることが わかります 古いリンカーは下位互換性のために 引き続きサポートされています 最も注目すべき点として armv7kリンカーはビルドできても 新しいリンカーはビルドできません armv7kアーキテクチャをサポートする 最後のプラットフォームはwatchOS 8でした watchOS 8以前にデプロイする 必要がない場合は バージョンをwatchOS 9にアップグレードして 新しいリンカーを使用します アプリ内でマージな可能ライブラリを 構築して使用する方法をですが 他社が使用できるようにライブラリを 配布したい場合はどうすれば? これを行うには Swift Package Manager内か XcodeでXCFrameworkを 作成します これにより配布用のメタデータを 含むフレームワークを構築できます 他のデベロッパがフレームワークを使用する場合 マージを有効にするかどうかを決定できます マージ可能なメタデータによりdylibの サイズはおよそ2倍になります メタデータはアプリのビルド後にマージ可能 ライブラリとともに― 破棄されるため アプリのサイズには影響しません それ以外の場合メタデータは アプリに埋め込む際の肥大化を 防ぐために削除されます マージ可能ライブラリに関するいくつかの ニュアンスについてご紹介しました それではおすすめの設定について 説明します マージされたバイナリに 依存関係を設定することが シームレスに導入するための鍵となります これはリンクの依存関係の 維持のため必須です スクリプト段階でバイナリを 必要とするツールにとって ライブラリをフィードする場合に 特に重要です 静的リンカーは直接の依存関係 のみをマージします 多くのマージ可能ライブラリを 含めるには それらを明示的なリンク依存関係として 設定する必要があります マージの設定はフレームワークの バイナリをディスクから削除するよう Xcodeビルドシステムに指示します 意図的でない場合は不具合が 発生することもあるため Xcodeターゲットレベルで 有効にすることをお勧めします 最後にパフォーマンスを最適化しつつ 生産性の面で最大のメリットを得るには 静的ライブラリを更新することを 検討してください 後で動的にマージできる 可能性があります マージ可能なライブラリは 利便性と柔軟性を提供します 自動ワークフローと 手動ワークフローの間で 好きなときにマージ可能ライブラリを 再構築して追加でき 必要なものをディスク上に残せます この柔軟性は段階的な導入や プロファイリングの際に有用です マージ可能ライブラリをフレームワーク および実行可能ターゲットに適用すると サイズやビルドに実行時間が 向上します 自動構成を使用してビルドシステムに 直接のフレームワークの 依存関係をマージさせることも可能です ただしどの依存関係をマージするかを 選択する必要がある場合は 手動モードでそれを実行することが 可能です マージ可能ライブラリを使用するよう プロジェクトを更新するときは ライブラリのすべての依存ライブラリが 削除されるライブラリの 代わりにマージされた バイナリに依存していることを 確認してください マージ可能ライブラリに関する 詳細については 「Configuring your project to use mergeable libraries」を 参照してください 静的リンクと動的リンクに関する詳細は 「Link fast: Improve build and launch times」 セッションをどうぞ あなたはマージ可能なライブラリを どうプロジェクトで使うでしょうか ありがとうございます
-
-
9:18 - Enabling library merging
MERGED_BINARY_TYPE
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。