Quando dovremmo usare i "binari incorporati" anziché "i frame collegati" in Xcode?


140

C'è una buona domanda sulla differenza tra queste due opzioni come descritto in Link Binary con librerie VS Embed Frameworks .

Sembra che abbiamo opzioni per usarli entrambi, ti chiedi quale caso dovremmo usare meglio i binari incorporati o piuttosto che un framework collegato?

Qualche esempio solido per affrontare questo più chiaro? Grazie


Risposte:


239

La domanda che hai collegato fa riferimento alla funzionalità "Collega binario con librerie", che è leggermente diversa da un binario incorporato.

"Collega binario con librerie" indica ciò che ti aspetteresti rispetto al collegamento: indipendentemente dal fatto che il binario sia una libreria statica, una libreria dinamica o un framework, sarà collegato al codice oggetto al momento del collegamento dopo la compilazione.

Quando pensi al collegamento con una libreria statica, ciò che accade è abbastanza chiaro: il linker copia il codice dalla libreria (ad es. libFoo.a) Nel tuo binario di output. Le dimensioni del file di output aumentano ma non è necessario risolvere dipendenze esterne in fase di runtime. Tutto ciò che il tuo programma deve eseguire (rispetto alla libreria statica) è presente dopo che è stato creato.

Con una libreria dinamica (.dylib o framework fornito dal sistema), l'aspettativa è che la libreria a cui ci si collega sia presente da qualche parte nel percorso del caricatore della libreria dinamica del sistema quando si esegue il programma. In questo modo non hai il sovraccarico di copiare tutte le librerie esterne di terze parti nel tuo binario e tutti i diversi programmi su un computer che si collegano anche a quella libreria saranno in grado di trovarlo, risparmiando spazio su disco minimo, ma anche potenzialmente spazio di memoria, a seconda di come e dove il sistema memorizza nella cache le librerie.

Un framework è molto simile a una libreria dinamica, ma può contenere risorse nella sua struttura di directory (immagini, audio, altri framework, ecc.). In questo caso un file statico-libreria o .dylib semplice non è tagliato in modo potrebbe essere necessario collegamento a un quadro solo così si può trovare ciò di cui ha bisogno per funzionare correttamente.

Quando si collega a un framework di terze parti (ad esempio qualcosa scaricato da Github e creato dall'utente), potrebbe non essere presente sul sistema su cui si intende eseguire. In questo caso, non solo si collegherebbe al framework, ma lo si incorporerebbe anche nel bundle dell'applicazione utilizzando la fase "Copia frame". Quando il programma viene eseguito, il runtime-linker (noto anche come resolver) guarderà all'interno del bundle oltre al percorso del caricatore di sistema, troverà il framework incorporato e lo collegherà in modo che l'app disponga del codice necessario per l'esecuzione.

Infine, ciò che è propriamente un "binario incorporato" è un eseguibile che entrambi incorporate nel bundle dell'applicazione tramite una fase di copia dei file e che eseguite da soli, magari con una chiamata popen()o simile. Il binario incorporato può essere chiamato dal tuo programma, ma non è collegato ad esso. È un'entità completamente esterna (come i programmi nella /bindirectory).

In pratica, per le librerie e i framework forniti dal sistema ti collegherai a loro e questo è tutto ciò che devi fare.

Se hai bisogno di collegare una libreria che hai creato che non ha bisogno di risorse incorporate (cioè non richiede l'esistenza di un framework), puoi semplicemente collegarti a una libreria statica. Se scopri di avere più moduli nel tuo programma che vogliono usare lo stesso codice di libreria, convertirlo in un framework o libreria dinamica e collegarlo può risparmiare spazio e può essere conveniente (in particolare se l'uso della memoria è un problema).

Infine, i framework possono includere non solo risorse, ma file di intestazione e / o licenza. L'utilizzo di un framework per trasmettere questi file è in realtà un comodo meccanismo di distribuzione, quindi spesso potresti voler incorporare un framework in modo che queste cose possano taggare insieme al tuo binario (cioè i requisiti di licenza potrebbero renderlo obbligatorio).

--- MODIFICARE ---

Adam Johns ha pubblicato la seguente domanda come commento:

Questa è un'ottima risposta C'è qualcosa su cui sono ancora un po 'confuso, comunque. Cosa significa eseguire il binario da soli? Vuoi dire semplicemente usando il codice del framework incorporato? So che hai menzionato popen (), ma stai dicendo che la mia app sta chiamando popen ()? Non so davvero cosa significhi.

Sto dicendo che un binario incorporato è solo un altro file di risorse nel tuo bundle, come un file audio o un'immagine, sebbene il file sia invece uno strumento da riga di comando eseguibile. La popen()funzione ( man popendal tuo terminale per saperne di più) ti consente di eseguire programmi arbitrari da un altro programma in esecuzione. La system()funzione è un altro modo. Ce ne sono altri, e qui darò un esempio storico che potrebbe rendere un po 'più chiaro la comprensione dell'uso di un binario incorporato:

Come probabilmente saprai, quando avvii un'app su Mac OS X questa viene avviata con un ID utente dell'utente corrente. Nelle installazioni più comuni è l'utente predefinito sul desktop admin, a cui viene assegnato l'ID utente 501.

Sui sistemi operativi basati su Unix solo l' rootutente (ID utente 0) ha pieno accesso all'intero filesystem. A volte capita che un programma di installazione avviato dall'utente Desktop debba installare i file in una directory privilegiata (ad esempio i driver). In questo caso, il programma applicativo deve inoltrare i propri privilegi rootall'utente in modo da poter scrivere in queste directory riservate.

Per facilitare ciò nei sistemi operativi tramite OS X 10.7, Apple ha fornito nella sua API dei servizi di autorizzazione la funzione AuthorizationExecuteWithPrivileges () (ora è obsoleta, ma è ancora un esempio utile).

AuthorizationExecuteWithPrivileges()ha preso come argomento un percorso a uno strumento da riga di comando per eseguire come root. Lo strumento da riga di comando era uno script della shell eseguibile o un file binario compilato scritto per eseguire la logica di installazione. Questo strumento è stato installato nel pacchetto dell'applicazione come qualsiasi altro file di risorse.

Quando viene chiamato, il sistema operativo attiva una finestra di dialogo di autorizzazione che richiede la password dell'utente (l'hai già vista prima!) E una volta inserito eseguirà il programma come rootper conto della tua app. Questo processo è simile all'esecuzione di un programma con popen()te stesso, anche se popen()da solo non ti dà il vantaggio di escalation di privilegi.


62
Come fai a sapere queste cose?
Ian Warburton,

56
@IanWarburton Sto programmando i sistemi operativi Apple da oltre 20 anni e ho preso qualche bocconcino qua e là. :)
par

1
@JustAMartin Intendo link, ma hai ragione a doverlo incorporare anche attraverso una fase di copia dei file (altrimenti come lo useresti ?). L'obiettivo dell'utilizzo di un framework di terze parti o di un binario incorporato è quello di eseguire il codice fornito dall'entità. Con un binario incorporato non è previsto alcun collegamento. In fase di esecuzione si costruisce un percorso per il binario, quindi lo si esegue manualmente. Con un framework il linker in fase di compilazione lo collegherà quando crei la tua app, quindi (se si tratta di un framework di terze parti) la incorpori tramite una fase di copia dei file e infine il linker di runtime la collega nuovamente quando esegui la tua app .
par

1
Le cose non sono chiare su cosa hai risposto a @JustAMartin. L'obiettivo dell'utilizzo di un framework di terze parti o di un binario incorporato è quello di eseguire il codice fornito dall'entità. Oggi i binari incorporati possono anche essere framework di terze parti. Sto cercando di capire cosa intendi qui ... AFA, ho capito, binari incorporati significa che binario separato del framework incorporato verrà introdotto nel bundle dell'app e se si collega semplicemente lo stesso framework, lo si inserirà nello stesso binario di quello dell'app. Per favore, correggimi se sbaglio ...
Hariszaman,

1
Forse c'è una nuova magia Xcode che caricherà un framework incorporato. È da un po 'che non ho bisogno di quella funzionalità. Se vuoi scoprire cosa succede di più, per favore pubblica una nuova domanda qui su SO.
par

35

In breve,

  • librerie di sistema, collegarle;
  • Librerie di terze parti, incorporale.

perché?

  • se provi a incorporare le librerie di sistema, non le troverai nell'elenco popup;
  • se colleghi librerie di terze parti, probabilmente otterrai un arresto anomalo.

7

Fa parte della Dependencygestione [Informazioni]

Si noti che Xcode 11contiene solo la Frameworks, Libraries, and Embedded Contentsezione nella Generalscheda

Link binario

Build Phases -> Link Binary With Librariesè uno specchio di General -> Linked Frameworks and Libraries.

Biblioteca statica e quadro

Se aggiungi a Static Library or Static Frameworka questa sezione, apparirà nel Frameworks gruppo [Informazioni] ( Project Navigator -> <workspace/project> -> Frameworks) e per questo verrà aggiunto un riferimento al tuo progetto. Quindi verrà utilizzato da Static Linker. Static Linkeral momento della compilazione includerà / copierà tutto il codice dalla libreria nel file oggetto eseguibile. Static linkerfunziona in coppia conBuild Settings -> <Library/Framework> Search Paths

Static Library

Static Framework

  • Build Settings -> Framework Search Paths. Se non si aggiunge a static frameworka questa sezione, verrà visualizzato un errore di compilazione [Nessun modulo di questo tipo]

Incorpora binario

Biblioteca statica e quadro statico

L'incorporamento non avrebbe alcun senso per un Static Librarye Static Frameworkperché i simboli da loro sono compilati nel binario eseguibile. Xcode non ti lascerà cadere static librarynella sezione Incorpora.

Quadro dinamico

Build Phases -> Embed Frameworksè uno specchio di General -> Embedded Binaries. L'incorporamento in realtà aggiunge una copia del framework nel pacchetto dell'applicazione. Di conseguenza, quando un framework viene aggiunto / rimosso nella Embedsezione verrà automaticamente aggiunto / rimosso nella Linkedsezione. Per impostazione predefinita, la cartella del pacchetto è Frameworksma è possibile modificarla utilizzando il Destinationcampo. Inoltre puoi specificare a Subpath.

Dynamic linker :dyldin fase di caricamento o di runtime tenterà di trovare il framework incorporato utilizzando @rpath[Informazioni] Se non viene trovato, si verificherà l'errore [dyld: libreria non caricata]

[Quando si utilizza Link and Embed]

[Vocabolario]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.