Xcodeで「リンクされたフレームワーク」ではなく「組み込みバイナリ」を使用する必要があるのはいつですか?


140

ライブラリとバイナリをリンクするVS Embed Frameworksで説明されているように、これら2つのオプションの違いについては良い質問があります。

両方を使用するオプションがあるようですが、どちらの場合に埋め込まれたバイナリをより適切に使用する必要があるのか​​、またはリンクされたフレームワークではなく、

これをより明確にする具体例はありますか?ありがとう


回答:


239

リンクした質問は、「バイナリをライブラリにリンクする」機能を参照しています。これは、埋め込みバイナリとは多少異なります。

「ライブラリとバイナリをリンクする」とは、リンケージに関して期待することを意味します。バイナリが静的ライブラリ、動的ライブラリ、フレームワークのいずれであるかに関係なく、コンパイル後のリンク時にオブジェクトコードにリンクされます。

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

動的ライブラリー(.dylib、またはシステム提供のフレームワーク)では、リンク先のライブラリーは、プログラムの実行時にシステムの動的ライブラリー・ローダーのパスのどこかに存在することが期待されます。これにより、サードパーティのすべての外部ライブラリをバイナリにコピーするオーバーヘッドがなくなり、そのライブラリにリンクしているコンピューター上のすべての異なるプログラムがそれを見つけることができるため、ディスク領域を最小限に節約できますが、システムがライブラリをキャッシュする方法と場所に応じて、潜在的にメモリ領域。

フレームワークは動的ライブラリによく似ていますが、ディレクトリ構造にリソース(イメージ、オーディオ、その他のフレームワークなど)を含めることができます。この場合、単純な静的ライブラリまたは.dylibファイルはそれをカットしないため適切に実行するために必要なものを見つけるために、フレームワークにリンクする必要がある場合があります。

サードパーティのフレームワーク(githubからダウンロードして自分でビルドしたものなど)にリンクすると、実行する予定のシステムに存在しない場合があります。この場合、フレームワークにリンクするだけでなく、「フレームワークのコピー」フェーズを使用して、アプリケーションバンドル内に埋め込みます。プログラムが実行されると、ランタイムリンカー(別名リゾルバー)がシステムローダーパスに加えてバンドル内を調べ、埋め込まれたフレームワークを見つけてリンクし、アプリを実行するために必要なコードを提供します。

最後に、適切に「組み込みバイナリ」とは、ファイルコピーフェーズを介して両方ともアプリケーションバンドルに埋め込んだ実行可能ファイルであり、おそらく呼び出しなどで自分で実行しますpopen()。埋め込まれたバイナリはプログラムから呼び出されることがありますが、リンクされていません。これは完全に外部のエンティティです(/binディレクトリ内のプログラムのように)。

実際には、システムが提供するライブラリとフレームワークの場合は、それらをリンクします。

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

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

---編集---

Adam Johnsがコメントとして次の質問を投稿しました:

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

私が言っている埋め込まれたバイナリは、ファイルの代わりに実行可能なコマンドラインツールですが、音声ファイルや画像のように、あなたのバンドル内のちょうど別のリソースファイルです。このpopen()機能(man popenターミナルから詳細を読む)を使用すると、実行中の別のプログラムから任意のプログラムを実行できます。system()機能は別の方法です。他にもありますが、ここでは、埋め込みバイナリの使用を少し明確にする歴史的な例を示します。

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

Unixベースのオペレーティングシステムでは、rootユーザー(ユーザーID 0)のみがファイルシステム全体へのフルアクセス権を持っています。デスクトップユーザーが起動したインストーラプログラムが、特権のあるディレクトリ(ドライバなど)にファイルをインストールする必要がある場合があります。この場合、アプリケーションプログラムはroot、これらの制限されたディレクトリに書き込むことができるように、その特権をユーザーに昇格させる必要があります。

OS X 10.7を介してオペレーティングシステムでこれを容易にするために、AppleはAuthorization Services APIに関数AuthorizationExecuteWithPrivileges()を提供しました(これは現在非推奨ですが、まだ有用な例です)。

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

呼び出されると、OSはユーザーのパスワードを要求する認証ダイアログを表示し(これは以前に確認したことです!)、入力するとroot、アプリに代わってプログラムが実行されます。このプロセスは、popen()自分でプログラムを実行するのと似ていますが、それpopen()だけでは特権の昇格のメリットはありません。


62
これらのことをどのようにして知っていますか?
Ian Warburton 2016

56
@IanWarburton私は20年以上Appleオペレーティングシステムをプログラミングしていて、あちこちでいくつかのヒントを拾ってきました。:)
2016

1
@JustAMartin linkつまり、ですが、ファイルのコピーフェーズを介して埋め込む必要があることは間違いありません(それ以外の場合はどのように使用しますか?)。サードパーティのフレームワークまたは埋め込みバイナリを使用する目的は、エンティティが提供するコードを実行することです。埋め込まれたバイナリでは、リンクは必要ありません。実行時にバイナリへのパスを作成し、手動で実行します。フレームワークを使用すると、アプリをビルドするときにコンパイル時リンカーがリンクします(サードパーティのフレームワークの場合)は、ファイルのコピーフェーズを介して埋め込み、最後に、アプリを実行するときにランタイムリンカーが再度リンクします。
パー

1
@JustAMartinに何を回答したかについては、少し不明確です。サードパーティのフレームワークまたは埋め込みバイナリを使用する目的は、エンティティが提供するコードを実行することです。今日、組み込みバイナリはサードパーティのフレームワークにもなります。ここであなたが何を意味するのかを理解しようとしています...埋め込まれたバイナリを意味するAFAは、埋め込まれたフレームワークの個別のバイナリがApp Bundleに導入され、同じフレームワークをリンクするだけで、それを同じバイナリに入れますアプリのこと。私の間違いを訂正してください...
hariszaman

1
おそらく、組み込みフレームワークをロードする新しいXcodeマジックがあるでしょう。その機能が必要になったので久しぶりです。何が起こっているのかを詳しく知りたい場合は、SOに新しい質問を投稿してください。
パー

35

要するに、

  • システムライブラリ、それらをリンクします。
  • サードパーティのライブラリ、それらを埋め込みます。

どうして?

  • システムライブラリを埋め込もうとしても、ポップアップリストに表示されません。
  • サードパーティのライブラリをリンクすると、おそらくクラッシュします。

7

Dependency経営の一部です【概要】

タブのセクションXcode 11のみが含まれていることに注意してくださいFrameworks, Libraries, and Embedded ContentGeneral

リンクバイナリ

Build Phases -> Link Binary With LibrariesはのミラーですGeneral -> Linked Frameworks and Libraries

静的ライブラリとフレームワーク

Static Library or Static Frameworkこのセクションにを追加すると、Frameworks グループ[概要]Project Navigator -> <workspace/project> -> Frameworks)に表示され、プロジェクトに参照が追加されます。次に、によって使用されStatic Linkerます。Static Linkerコンパイル時に、ライブラリのすべてのコードを実行可能オブジェクトファイルにインクルード/コピーします。Static linkerと組み合わせて動作しますBuild Settings -> <Library/Framework> Search Paths

Static Library

Static Framework

バイナリを埋め込む

静的ライブラリと静的フレームワーク

埋め込みはのためにどんな意味がありませんStatic Libraryし、Static Frameworkそれらからのシンボルは実行可能なバイナリにコンパイルされているため。Xcode static libraryでは、埋め込みセクションの下にaをドロップできません。

動的フレームワーク

Build Phases -> Embed FrameworksはのミラーですGeneral -> Embedded Binaries。実際に埋め込むと、フレームワークのコピーがアプリケーションバンドルに追加されます。その結果、フレームワークがEmbedセクションに追加/削除されると、自動的にLinkedセクションに追加/削除されます。デフォルトでは、バンドルのフォルダーはですFrameworksが、Destinationフィールドを使用して変更できます。さらに、を指定できますSubpath

Dynamic linker :dyld、ロードまたは実行時見つけようとします埋め込まれたフレームワークを使用して@rpath、[概要]には、エラーが発生しますが見つからない場合は、[dyldの:ライブラリがロードされていません]

【リンクと埋め込みを使用する場合】

[単語]

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.