Library
概要
Library とは?
Library とは、1つないし複数のアーキテクチャ用にコンパイルされた オブジェクトファイル の集まりを指す。そして、オブジェクトファイルとは、コンパイラによって出力された、機械語を含むファイル のことをいい、iOS, macOS では Mach-O というフォーマットが標準的に用いられている。
このように、外部の Library とアプリケーションのソースコードファイルをマージするプロセスは リンク と呼ばれ、リンカ によって行われる。このリンクの方式によって、Library の種類は Static Library と Dynamic Library の2つに大別できる。
Dynamic Library
Dynamic Library とは?
Static Library が実行形式ファイル内にコピーされる一方、Dynamic Library は必要となった際にメモリ上にロードして利用される。そのため、アプリケーションの実行形式ファイル内には含まれない。通常、Dynamic Library はアプリケーション間で共有されるため、システムは1つのライブラリのコピーのみを保持し、それに複数の異なるプロセスがアクセスする。
このような性質のため、Dynamic Library からのコードのロードは Static Library よりも遅い。ただし、実行形式ファイルのサイズは小さくなり、ライブラリに修正が加えられても再度コンパイルせずにそれを反映できる。
拡張子は .dylib であり、他のプラットフォームでは DSO, DLL などとして知られる。
全ての iOS, macOS システムライブラリは Dynamic Library である (Foundation や UIKit など)。このおかげで、Apple によってシステムライブラリが更新された後でも、アプリケーション側でビルドのし直しをせずとも、その更新を反映できる。また、これをサポートするために、Dynamic Library は複数バージョンのコード, データをその内容に含めることができる。
Text-based .dylib stub
UIKit や Foundation 等のシステムライブラリをアプリケーションに含めてしまうと、サイズが大きくなりすぎてしまうのでできるだけ避けたい。リンカーも同様で、共有の .dylib ライブラリをリンクするのではなく、.tbd という拡張子のファイルのみをリンクするようになっている。
テキストベースの .dylib スタブ、あるいは .tbd とは、Dynamic Library のメソッド名を含んだテキストファイルである。利用する Dynamic Library のメソッド名に加え、アーキテクチャやプラットフォーム等のメタデータのみを含んでおり、.dylib ファイルそれ自体よりもかなり小さい容量ですむ。
Static Library vs Dynamic Library
各々のメリット, デメリットは以下のようになる。
table:vs
アプリサイズ 起動時間 Library関数のロード ライブラリの更新
Static Library 大きい ❌ 遅い ❌ 早い ⭕ 再コンパイルが必要 ❌, アプリ側で追従が不要 ⭕
Dynamic Library 小さい ⭕ 早い ⭕ 遅い ❌ 再コンパイルが必要ない ⭕, アプリ側で追従が必要 ❌
ライブラリの更新については、Static Library は固定バージョンで利用し続けることになるので、ライブラリの更新を行うためには再コンパイルが必要だが、ライブラリの更新によってアプリが壊れることがなく、利用しているライブラリのバージョンも固定できるというメリットがある。Dynamic Library はライブラリの更新にアプリを再コンパイルしなくても追従できるが、ライブラリ側の問題でアプリに問題が生じる可能性もある。
iOSアプリの起動速度を2倍にするために、複数のDynamic FrameworkをStaticにして、ひとつのDynamic Frameworkを作る with Swift
Tips: Support Tools
otool
Linux には objdump という、オブジェクトファイルの情報を表示するコマンドがある。macOS 環境にて、Mach-O 形式のオブジェクトファイルに対し同等の情報を得たい場合には、otool を利用すると良いとのこと。
https://forums.developer.apple.com/thread/64494
例えば、適当な iOS プロジェクトから生成されたオブジェクトファイルに対して利用してみる。例えば、Xcode のシミュレータ用のビルド成果物は Users/<ユーザ名>/Library/Developer/Xcode/DerivedData/<プロジェクト名>-<識別子>/Build/Products/Debug-iphonesimulator 以下に存在する。そこに各 Framework やアプリ自身のビルド結果がある。アプリ自身のビルド結果に対し、otool を下記のように利用すると、動的リンクされる Dynamic Library の一覧を表示できる。Foundation や UIKit が Dynamic Library としてリンクされることがわかる。
code:shell
$ otool -L MyApp.app/MyApp
MyApp.app/MyApp:
/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1665.15.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 61000.0.0)
/usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 1100.2.255)
/usr/lib/swift/libswiftFoundation.dylib (compatibility version 1.0.0, current version 0.0.0)
/usr/lib/swift/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 0.0.0)
https://qiita.com/shu223/items/f009c4cd63625ccc44a9
file
file コマンドを利用すると、そのファイル自体が Dynamic Library であるか、実行可能なオブジェクトファイルであるかなどがわかる。例えば、アプリ自体に以下のように使用すると、アプリが Mach-O フォーマットの実行可能形式のファイルにコンパイルされていることがわかる。
code:shell
$ file MyApp.app/MyApp
MyApp.app/MyApp: Mach-O 64-bit executable x86_64
その他、Static Library, Dynamic Library の場合は以下のように表示されるようだった。
code:sh
# Static Library としてリンクする場合
$ file RxCocoa/RxCocoa.framework/RxCocoa
RxCocoa/RxCocoa.framework/RxCocoa: current ar archive
# Dynamic Library としてリンクする場合
$ file RxCocoa/RxCocoa.framework/RxCocoa
RxCocoa/RxCocoa.framework/RxCocoa: Mach-O 64-bit dynamically linked shared library x86_64
参考
Static and Dynamic Libraries and Frameworks in IOS
BASIC OVERVIEW OF STATIC AND DYNAMIC FRAMEWORKS ON IOS
lipo Man Page