1. ホーム
  2. ios

[解決済み] Xcodeで「Linked Frameworks」ではなく「embedded binaries」を使用すべきなのはどのような場合ですか?

2022-05-05 12:29:33

質問

で説明した2つのオプションの違いについて、良い質問があります。 バイナリとライブラリのリンク VS フレームワークの埋め込み .

両方使えるオプションがあるように見えますが、どちらのケースで埋め込みバイナリを使うべきか、あるいはリンクされたフレームワークではなく、埋め込みバイナリを使うべきか、疑問に思っています。

この問題をより明確に扱うための確かな事例があれば教えてください。 ありがとうございます。

どのように解決するのですか?

リンク先の質問は、"Link Binary With Libraries" 機能を参照していますが、これは埋め込みバイナリとはやや異なります。

バイナリリンクは、リンクに関してあなたが期待するものを意味します。バイナリがスタティック・ライブラリ、ダイナミック・ライブラリ、フレームワークのいずれであるかに関係なく、コンパイル後のリンク時にオブジェクト・コードにリンクされます。

静的ライブラリのリンケージを考えるとき、何が起こるかは非常に明確です:リンカーが がコピーします。 のコード(たとえば libFoo.a ) を出力バイナリに挿入します。 出力ファイルのサイズは大きくなりますが、実行時に外部依存を解決する必要はありません。 プログラムの実行に必要なもの (静的ライブラリに関するもの) はすべて、ビルドされた後に存在することになります。

動的ライブラリ(.dylib、またはシステム提供のフレームワーク)では、プログラムを実行するときに、リンク先のライブラリがシステムの動的ライブラリ・ローダーのパスのどこかに存在することが期待されます。 この方法では、サードパーティの外部ライブラリをすべてバイナリにコピーするオーバーヘッドがなく、そのライブラリにリンクするコンピュータ上のすべての異なるプログラムがそれを見つけることができるため、ディスク容量を最小限に抑えられますが、システムがライブラリをどのように、どこにキャッシュするかによって、メモリ容量も抑えられる可能性があります。

フレームワークは、ダイナミックライブラリとよく似ていますが、そのディレクトリ構造にリソース(画像、オーディオ、他のフレームワークなど)を含むことができます。 この場合、単純なスタティックライブラリや.dylibファイルでは不十分なので、フレームワークにリンクする必要があるかもしれません。 それ は、適切に動作するために必要なものを見つけることができます。

サードパーティのフレームワークにリンクする場合(たとえばgithubからダウンロードして自分でビルドしたもの)、実行しようとするシステム上にそれが存在しない可能性があります。 この場合、フレームワークにリンクするだけでなく、"Copy Frameworks" フェーズを使用して、アプリケーションバンドル内にフレームワークを組み込むことになります。 プログラムが実行されると、ランタイムリンカー (別名リゾルバ) はシステムローダパスに加えてバンドル内を探し、埋め込まれたフレームワークを見つけ、それをリンクして、アプリが実行するために必要なコードを持つようにします。

最後に、正しくは「埋め込みバイナリ」ですが、これは Copy-Files フェーズでアプリケーションバンドルに埋め込み、自分で実行する実行ファイルです。 popen() などがあります。 埋め込みバイナリは、あなたのプログラムから呼び出されるかもしれませんが、 プログラムとリンクされているわけではありません。 それは完全に外部のエンティティです。 /bin ディレクトリ)。

実際には、システム提供のライブラリやフレームワークについては、それらに対してリンクすることになり、それだけで十分です。

組み込みリソースを必要としない(つまりフレームワークの存在を必要としない)ビルドしたライブラリをリンクする必要がある場合、静的ライブラリに対してリンクすればよいのです。 もし、プログラム中に同じライブラリコードを使いたいモジュールが複数ある場合、フレームワークまたはダイナミックライブラリに変換してリンクすると、スペースを節約でき、便利です(特にメモリ使用量が懸念される場合)。

最後に、フレームワークには、リソースだけでなく、ヘッダーファイルやライセンスファイルを含めることができます。 これらのファイルを伝えるためにフレームワークを使用することは、実際に便利な配布メカニズムであり、しばしば、これらのものがバイナリと共にタグ付けできるようにフレームワークを組み込むことを望むかもしれません(すなわち、ライセンス要件がこれを必須とするかもしれません)。

--- EDIT(エディット) ---。

Adam Johnsさんがコメントとして以下の質問を投稿してくれました。

これは素晴らしい回答です。しかし、まだ少し混乱していることがあります。バイナリを自分で実行するというのはどういうことでしょうか?単に組み込みフレームワークのコードを使うということでしょうか?popen()について言及されていますが、私のアプリがpopen()を呼び出していると言うことでしょうか?それが何を意味するのかよくわかりません。

私が言っているのは 埋め込みバイナリ は、オーディオファイルや画像のように、バンドル内の単なるリソースファイルですが、このファイルは代わりに実行可能なコマンドラインツールになっています。その popen() 関数( man popen を使用すると、実行中のプログラムから任意のプログラムを実行することができます。また system() 関数もその一つです。他にもありますが、ここでは歴史的な例を挙げて、埋め込みバイナリの使い方をもう少し明確に理解できるようにします。

ご存知のように、Mac OS Xでアプリを起動すると、現在のユーザーのユーザーIDで起動されます。ほとんどの一般的なインストールでは、デスクトップにいるデフォルトのユーザーである admin ユーザは、ユーザID 501 .

Unix系OSでは root ユーザー(ユーザーID 0 ) は、ファイルシステム全体へのフルアクセス権を持ちます。Desktopユーザーによって起動されたインストーラープログラムが、特権ディレクトリにファイルをインストールする必要がある場合があります(たとえば、ドライバ)。この場合、アプリケーションプログラムは特権を root ユーザで書き込みができるようになります。

OS X 10.7までのOSでは、これを容易にするために、Appleはその 認証サービス API 関数 AuthorizationExecuteWithPrivileges() (これは現在では非推奨ですが、まだ有用な例です)。

AuthorizationExecuteWithPrivileges() は、実行するコマンドラインツールへのパスを引数として取りました。 root . コマンドラインツールは、インストールロジックを実行するために記述した、実行可能なシェルスクリプトまたはコンパイルされたバイナリです。このツールは、他のリソースファイルと同じようにアプリケーションバンドル内にインストールされます。

呼び出されると、OSはユーザーのパスワードを尋ねる認証ダイアログを表示し(前に見たことあるでしょ!)、入力されると、プログラムを root を、あなたのアプリに代わって実行します。この処理は単に popen() を使用しますが popen() だけでは、特権昇格の恩恵は受けられません。