Es gibt eine gute Frage zum Unterschied zwischen diesen beiden Optionen, wie unter Link Binär mit Bibliotheken VS Embed Frameworks beschrieben .
Scheint, als hätten wir Optionen, um beide zu verwenden. Fragen Sie sich nur, in welchem Fall wir eingebettete Binärdateien besser verwenden sollten, als ein verknüpftes Framework.
Gibt es solide Beispiele, um dies klarer anzugehen? Vielen Dank
Antworten:
Die von Ihnen verknüpfte Frage bezieht sich auf die Funktion "Binär mit Bibliotheken verknüpfen", die sich etwas von einer eingebetteten Binärdatei unterscheidet.
"Binär mit Bibliotheken verknüpfen" bedeutet, was Sie in Bezug auf die Verknüpfung erwarten würden: Unabhängig davon, ob es sich bei der Binärdatei um eine statische Bibliothek, eine dynamische Bibliothek oder ein Framework handelt, wird sie zum Zeitpunkt der Verknüpfung nach der Kompilierung mit Ihrem Objektcode verknüpft.
Wenn Sie an eine Verknüpfung mit einer statischen Bibliothek denken, ist das, was passiert, ziemlich klar: Der Linker kopiert den Code aus der Bibliothek (z. B.
libFoo.a
) in Ihre Ausgabe-Binärdatei. Ihre Ausgabedatei wird größer, muss jedoch zur Laufzeit keine externen Abhängigkeiten auflösen. Alles, was Ihr Programm ausführen muss (in Bezug auf die statische Bibliothek), ist nach der Erstellung vorhanden.Bei einer dynamischen Bibliothek (.dylib oder vom System bereitgestelltes Framework) wird erwartet, dass die Bibliothek, mit der Sie verknüpfen, beim Ausführen Ihres Programms irgendwo im Ladepfad der dynamischen Bibliothek des Systems vorhanden ist. Auf diese Weise haben Sie nicht den Aufwand, alle externen Bibliotheken von Drittanbietern in Ihre Binärdatei zu kopieren, und alle verschiedenen Programme auf einem Computer, die ebenfalls mit dieser Bibliothek verknüpft sind, können sie finden, was aber auch minimalen Speicherplatz spart Möglicherweise Speicherplatz, abhängig davon, wie und wo das System Bibliotheken zwischenspeichert.
Ein Framework ähnelt einer dynamischen Bibliothek, kann jedoch Ressourcen in seiner Verzeichnisstruktur enthalten (Bilder, Audio, andere Frameworks usw.). In diesem Fall wird eine einfache statische Bibliothek oder eine .dylib-Datei nicht geschnitten, sodass Sie möglicherweise eine Verknüpfung zu einem Framework herstellen müssen, damit es findet, was für eine ordnungsgemäße Ausführung erforderlich ist.
Wenn Sie eine Verknüpfung zu einem Framework eines Drittanbieters herstellen (z. B. etwas, das Sie von github heruntergeladen und selbst erstellt haben), ist es möglicherweise nicht auf dem System vorhanden, auf dem Sie ausgeführt werden möchten. In diesem Fall würden Sie nicht nur eine Verknüpfung zum Framework herstellen, sondern es auch mithilfe der Phase "Frameworks kopieren" in Ihr Anwendungspaket einbetten. Wenn Ihr Programm ausgeführt wird, wird der Laufzeit-Linker (auch als Resolver bezeichnet) zusätzlich zum Systemladepfad in Ihrem Bundle nachsehen, das eingebettete Framework finden und verknüpfen, damit Ihre App den Code hat, den sie zum Ausführen benötigt.
Was eigentlich eine "eingebettete Binärdatei" ist, ist eine ausführbare Datei, die Sie beide über eine Phase "Dateien kopieren" in Ihr Anwendungspaket einbetten und die Sie selbst ausführen, möglicherweise mit einem Aufruf von
popen()
oder ähnlichem. Die eingebettete Binärdatei wird möglicherweise von Ihrem Programm aufgerufen, ist jedoch nicht damit verknüpft. Es ist eine vollständig externe Entität (wie Programme im/bin
Verzeichnis).In der Praxis werden Sie für vom System bereitgestellte Bibliotheken und Frameworks einen Link zu diesen erstellen, und das ist alles, was Sie tun müssen.
Wenn Sie eine von Ihnen erstellte Bibliothek verknüpfen müssen, für die keine eingebetteten Ressourcen erforderlich sind (dh für die kein Framework erforderlich ist), können Sie einfach eine Verknüpfung mit einer statischen Bibliothek herstellen. Wenn Sie feststellen, dass Ihr Programm mehrere Module enthält, die denselben Bibliothekscode verwenden möchten, kann das Konvertieren in ein Framework oder eine dynamische Bibliothek und das Verknüpfen mit diesem Modul Platz sparen und praktisch sein (insbesondere, wenn die Speichernutzung ein Problem darstellt).
Schließlich können Frameworks nicht nur Ressourcen, sondern auch Header- und / oder Lizenzdateien enthalten. Die Verwendung eines Frameworks zur Übermittlung dieser Dateien ist eigentlich ein praktischer Verteilungsmechanismus, so dass Sie häufig ein Framework einbinden möchten, damit diese Dinge zusammen mit Ihrer Binärdatei markiert werden können (dh Lizenzanforderungen können dies obligatorisch machen).
--- BEARBEITEN ---
Adam Johns hat die folgende Frage als Kommentar gepostet:
Ich sage, eine eingebettete Binärdatei ist nur eine andere Ressourcendatei in Ihrem Bundle, wie eine Audiodatei oder ein Bild, obwohl die Datei stattdessen ein ausführbares Befehlszeilentool ist. Mit der
popen()
Funktion (man popen
von Ihrem Terminal aus, um mehr darüber zu erfahren) können Sie beliebige Programme von einem anderen laufenden Programm ausführen. Diesystem()
Funktion ist ein anderer Weg. Es gibt andere, und ich werde hier ein historisches Beispiel geben, das das Verständnis der Verwendung einer eingebetteten Binärdatei etwas klarer macht:Wie Sie wahrscheinlich wissen, wird eine App unter Mac OS X mit einer Benutzer-ID des aktuellen Benutzers gestartet. Bei den meisten gängigen Installationen ist dies der Standardbenutzer am Desktop
admin
, dem die Benutzer-ID zugewiesen wird501
.Unter Unix-basierten Betriebssystemen hat nur der
root
Benutzer (Benutzer-ID0
) vollen Zugriff auf das gesamte Dateisystem. Manchmal muss ein vom Desktop-Benutzer gestartetes Installationsprogramm Dateien in einem privilegierten Verzeichnis installieren (z. B. Treiber). In diesem Fall muss das Anwendungsprogramm seine Berechtigungen an denroot
Benutzer weitergeben, damit es in diese eingeschränkten Verzeichnisse schreiben kann.Um dies unter Betriebssystemen unter OS X 10.7 zu vereinfachen, hat Apple in seiner Authorization Services-API die Funktion AuthorizationExecuteWithPrivileges () bereitgestellt (dies ist jetzt veraltet, aber immer noch ein nützliches Beispiel).
AuthorizationExecuteWithPrivileges()
nahm als Argument einen Pfad zu einem Befehlszeilentool, das als ausgeführt werden sollroot
. Das Befehlszeilentool war ein ausführbares Shell-Skript oder eine kompilierte Binärdatei, die Sie zum Ausführen Ihrer Installationslogik geschrieben haben. Dieses Tool wurde wie jede andere Ressourcendatei in Ihrem Anwendungspaket installiert.Wenn das Betriebssystem aufgerufen wird, wird ein Autorisierungsdialogfeld angezeigt, in dem Sie nach dem Kennwort des Benutzers gefragt werden (das haben Sie bereits gesehen!). Bei Eingabe wird das Programm wie
root
im Namen Ihrer App ausgeführt. Dieser Vorgang ähnelt dem Ausführen eines Programms mit sichpopen()
selbst,popen()
bietet Ihnen jedoch allein nicht den Vorteil einer Eskalation von Berechtigungen.quelle
link
, aber Sie haben Recht , dass Sie es auch über eine Kopierdatei-Phase einbetten müssen (wie würden Sie es sonst verwenden?). Das Ziel der Verwendung eines Frameworks eines Drittanbieters oder einer eingebetteten Binärdatei besteht darin, den von der Entität bereitgestellten Code auszuführen. Bei einer eingebetteten Binärdatei ist keine Verknüpfung erforderlich. Zur Laufzeit erstellen Sie einen Pfad zur Binärdatei und führen ihn dann manuell aus. Mit einem Framework verknüpft der Linker zur Kompilierungszeit es, wenn Sie Ihre App erstellen. Wenn es sich um ein Framework eines Drittanbieters handelt, binden Sie es über eine Phase zum Kopieren von Dateien ein. Schließlich verknüpft der Laufzeit-Linker es erneut, wenn Sie Ihre App ausführen .Zusamenfassend,
Warum?
quelle
Es ist ein Teil des
Dependency
Managements [About]Bitte beachten Sie, dass
Xcode 11
nur einFrameworks, Libraries, and Embedded Content
Abschnitt in derGeneral
Registerkarte enthältLink Binär
Build Phases -> Link Binary With Libraries
ist ein Spiegel vonGeneral -> Linked Frameworks and Libraries
.Statische Bibliothek und Framework
Wenn Sie
Static Library or Static Framework
diesem Abschnitt ein hinzufügen , wird es in derFrameworks
Gruppe [Info] (Project Navigator -> <workspace/project> -> Frameworks
) angezeigt und Ihrem Projekt wird ein Verweis hinzugefügt. Dann wird es von verwendetStatic Linker
.Static Linker
Beim Kompilieren wird der gesamte Code aus der Bibliothek in die ausführbare Objektdatei aufgenommen / kopiert .Static linker
arbeitet zusammen mitBuild Settings -> <Library/Framework> Search Paths
Static Library
Build Settings -> Library Search Paths
[Bibliothek nicht gefunden] Wenn Siestatic library
diesem Abschnittkein hinzufügen, wird ein Linkerfehler angezeigt [ld: Symbol (e) nicht gefunden]Static Framework
Build Settings -> Framework Search Paths
. Wenn Siestatic framework
diesem Abschnitt kein hinzufügen , wird ein Kompilierungsfehler angezeigt [Kein solches Modul]Binär einbetten
Statische Bibliothek und statisches Framework
Das Einbetten würde für a keinen Sinn machen
Static Library
undStatic Framework
weil die Symbole aus ihnen in die ausführbare Binärdatei kompiliert werden. Mit Xcode können Sie keinstatic library
unter dem Abschnitt Einbetten ablegen.Dynamisches Framework
Build Phases -> Embed Frameworks
ist ein Spiegel vonGeneral -> Embedded Binaries
. Durch das Einbetten wird Ihrem Anwendungspaket tatsächlich eine Kopie des Frameworks hinzugefügt. Wenn ein Framework zu einemEmbed
Abschnitt hinzugefügt / daraus entfernt wird, wird es automatisch zu einemLinked
Abschnitt hinzugefügt / daraus entfernt . Standardmäßig befindet sich der Ordner des BundlesFrameworks
, Sie können ihn jedoch mithilfe desDestination
Felds ändern . Außerdem können Sie a angebenSubpath
.Dynamic linker :dyld
Beim Laden oder Ausführen wird versucht, das eingebettete Framework mit@rpath
[Info] zu finden. Wenn es nicht gefunden wird, tritt der Fehler auf [dyld: Bibliothek nicht geladen][Bei Verwendung von Link und Einbetten]
[Wortschatz]
quelle