¿Cuándo deberíamos usar "binarios incrustados" en lugar de "Frameworks vinculados" en Xcode?

140

Hay una buena pregunta sobre la diferencia entre esas dos opciones como se describe en Enlace binario con bibliotecas VS Embed Frameworks .

Parece que tenemos opciones para usarlos a ambos, solo me pregunto en qué caso deberíamos usar mejor los binarios incrustados, o en lugar del marco vinculado.

¿Algún ejemplo sólido para abordar esto más claro? Gracias

Para descanso
fuente

Respuestas:

239

La pregunta que ha vinculado hace referencia a la funcionalidad "Vincular binario con bibliotecas", que es algo diferente de un binario incrustado.

"Enlace binario con bibliotecas" significa lo que esperaría con respecto al enlace: Independientemente de si el binario es una biblioteca estática, una biblioteca dinámica o un marco, estará vinculado a su código de objeto en el momento del enlace después de la compilación.

Cuando piensa en la vinculación con una biblioteca estática, lo que sucede es bastante claro: el vinculador copia el código de la biblioteca (por ejemplo libFoo.a) en su binario de salida. Su archivo de salida aumenta de tamaño pero no necesita resolver ninguna dependencia externa en tiempo de ejecución. Todo lo que su programa necesita para ejecutarse (con respecto a la biblioteca estática) está presente después de su creación.

Con una biblioteca dinámica (.dylib, o marco proporcionado por el sistema), la expectativa es que la biblioteca con la que se está vinculando estará presente en algún lugar de la ruta del cargador de la biblioteca dinámica del sistema cuando ejecute su programa. De esta manera no tiene la sobrecarga de copiar todas las bibliotecas externas de terceros en su binario, y todos los diferentes programas en una computadora que también se vinculan a esa biblioteca podrán encontrarla, lo que ahorra un mínimo espacio en disco, pero también potencialmente espacio de memoria, dependiendo de cómo y dónde el sistema almacena en caché las bibliotecas.

Un marco es muy parecido a una biblioteca dinámica, pero puede contener recursos en su estructura de directorios (imágenes, audio, otros marcos, etc.). En este caso, una simple biblioteca estática o un archivo .dylib no lo cortará, por lo que es posible que deba vincular a un marco solo para que pueda encontrar lo que necesita para ejecutarse correctamente.

Cuando se vincula a un marco de terceros (digamos algo que descargó de github y creó usted mismo), es posible que no esté presente en el sistema en el que desea ejecutar. En este caso, no solo se vincularía al marco, sino que también lo incrustaría dentro del paquete de la aplicación utilizando la fase "Copiar marcos". Cuando se ejecuta su programa, el runtime-linker (también conocido como el resolutor) buscará dentro de su paquete además de la ruta del cargador del sistema, encontrará el marco incrustado y lo vinculará para que su aplicación tenga el código que necesita para ejecutarse.

Finalmente, lo que es propiamente un "binario incrustado" es un ejecutable que ambos incrustan en su paquete de aplicaciones a través de una Fase de Copiar Archivos, y que usted mismo ejecuta, tal vez con una llamada popen()o similar. El programa puede llamar al binario incrustado, pero no está vinculado con él. Es una entidad totalmente externa (como los programas en el /bindirectorio).

En la práctica, para bibliotecas y marcos proporcionados por el sistema, se vinculará con ellos y eso es todo lo que necesita hacer.

Si necesita vincular una biblioteca que creó que no necesita ningún recurso incrustado (es decir, no requiere que exista un marco), puede simplemente vincular con una biblioteca estática. Si descubre que tiene varios módulos en su programa que desean usar el mismo código de biblioteca, luego convertirlo en un marco o biblioteca dinámica y vincularlo puede ahorrar espacio y puede ser conveniente (particularmente si el uso de memoria es una preocupación).

Finalmente, los marcos pueden incluir no solo recursos, sino también encabezados y / o archivos de licencia. El uso de un marco para transmitir estos archivos es en realidad un mecanismo de distribución conveniente, por lo que a menudo es posible que desee incorporar un marco solo para que estas cosas puedan etiquetarse junto con su binario (es decir, los requisitos de licencia pueden hacer que esto sea obligatorio).

--- EDITAR ---

Adam Johns publicó la siguiente pregunta como comentario:

Esta es una respuesta genial. Sin embargo, hay algo en lo que todavía estoy un poco confundido. ¿Qué significa ejecutar el binario usted mismo? ¿Te refieres a simplemente usar el código del marco incrustado? Sé que mencionaste popen (), pero ¿estás diciendo que mi aplicación está llamando popen ()? Realmente no sé lo que eso significa.

Estoy diciendo que un binario incrustado es solo otro archivo de recursos en su paquete, como un archivo de audio o una imagen, aunque el archivo es en cambio una herramienta de línea de comandos ejecutable. La popen()función ( man popendesde su terminal para leer más al respecto) le permite ejecutar programas arbitrarios desde otro programa en ejecución. La system()función es otra forma. Hay otros, y daré un ejemplo histórico aquí que puede aclarar un poco más el uso de un binario incrustado:

Como probablemente sepa, cuando inicia una aplicación en Mac OS X, se inicia con una identificación de usuario del usuario actual. En las instalaciones más comunes, ese es el usuario predeterminado de usuario en el escritorio admin, a quien se le asigna la identificación de usuario 501.

En los sistemas operativos basados ​​en Unix, solo el rootusuario (ID de usuario 0) tiene acceso completo a todo el sistema de archivos. A veces sucede que un programa instalador lanzado por el usuario de Desktop necesita instalar archivos en un directorio privilegiado (controladores, por ejemplo). En este caso, el programa de aplicación necesita escalar sus privilegios al rootusuario para que pueda escribir en estos directorios restringidos.

Para facilitar esto en los sistemas operativos a través de OS X 10.7, Apple proporcionó en su API de servicios de autorización la función AuthorizationExecuteWithPrivileges () (ahora está en desuso, pero sigue siendo un ejemplo útil).

AuthorizationExecuteWithPrivileges()tomó como argumento una ruta a una herramienta de línea de comandos para ejecutar como root. La herramienta de línea de comandos era un script de shell ejecutable o un binario compilado que escribiste para ejecutar tu lógica de instalación. Esta herramienta se instaló dentro de su paquete de aplicaciones como cualquier otro archivo de recursos.

Cuando se le llama, el sistema operativo muestra un cuadro de diálogo de autorización que solicita la contraseña del usuario (¡ya lo ha visto antes!) Y, cuando se ingresa, ejecuta el programa como rooten nombre de su aplicación. Este proceso es similar a solo ejecutar un programa popen()contigo mismo, aunque popen()solo no te da el beneficio de la escalada de privilegios.

par
fuente
62
¿Cómo sabes estas cosas?
Ian Warburton
56
@IanWarburton He estado programando los sistemas operativos de Apple durante más de 20 años y he recogido algunas cositas aquí y allá. :)
par
1
@JustAMartin Quiero decir link, pero tienes razón en que también tienes que incrustarlo a través de una fase de copia de archivos (de lo contrario, ¿cómo lo usarías ?). El objetivo de usar un marco de terceros o un binario incrustado es ejecutar el código que proporciona la entidad. Con un binario incrustado no se involucra ningún enlace. En tiempo de ejecución construye una ruta al binario y luego lo ejecuta manualmente. Con un marco, el vinculador en tiempo de compilación lo vinculará cuando construya su aplicación, luego (si es un marco de terceros) lo incrustará a través de una fase de copia de archivos, y finalmente el vinculador de tiempo de ejecución lo vinculará nuevamente cuando ejecute su aplicación .
par
1
Las cosas no están claras en cuanto a lo que respondió a @JustAMartin. El objetivo de usar un marco de terceros o un binario incrustado es ejecutar el código que proporciona la entidad. Hoy en día, los binarios incrustados también pueden ser marcos de terceros. Estoy tratando de entender lo que quiere decir aquí ... AFA Lo entendí, binarios incrustados significa que se introducirá un binario separado del marco incrustado en el paquete de aplicaciones, y si solo vincula el mismo marco, lo pondría en el mismo binario que el de app. Por favor
corrígeme
1
Tal vez haya una nueva magia de Xcode que cargará un marco incrustado. Ha pasado un tiempo desde que necesitaba esa funcionalidad. Si desea explorar qué está sucediendo más, publique una nueva pregunta aquí en SO.
par
35

En breve,

  • bibliotecas del sistema, vincularlas;
  • Bibliotecas de terceros, incrustarlas.

¿por qué?

  • si intenta incrustar bibliotecas del sistema, no las encontrará en la lista emergente;
  • si vincula bibliotecas de terceros, probablemente obtendrá un bloqueo.
Futuro brillante
fuente
7

Es parte de la Dependencygestión [Acerca de]

Tenga en cuenta que Xcode 11solo contiene una Frameworks, Libraries, and Embedded Contentsección en la Generalpestaña

Enlace binario

Build Phases -> Link Binary With Librarieses un espejo de General -> Linked Frameworks and Libraries.

Biblioteca estática y marco

Si agrega una Static Library or Static Frameworka esta sección, aparecerá en el Frameworks grupo [Acerca de] ( Project Navigator -> <workspace/project> -> Frameworks) y se agregará una referencia a su proyecto para ello. Entonces será utilizado por Static Linker. Static Linkeren tiempo de compilación incluirá / copiará todo el código de la biblioteca en el archivo objeto ejecutable. Static linkertrabaja en pareja conBuild Settings -> <Library/Framework> Search Paths

Static Library

Static Framework

  • Build Settings -> Framework Search Paths. Si no agrega un static frameworka esta sección, recibirá un error de compilación [No existe tal módulo]

Incrustar binario

Biblioteca estática y marco estático

Incrustación no tendría ningún sentido para una Static Libraryy Static Frameworkporque los símbolos de ellos se compilan en el binario ejecutable. Xcode no le permitirá colocar un static librarydebajo de la sección Incrustar.

Marco Dinámico

Build Phases -> Embed Frameworkses un espejo de General -> Embedded Binaries. La incrustación en realidad agrega una copia del marco en su paquete de aplicaciones. Como resultado, cuando se agrega / elimina un marco a la Embedsección, se agregará / eliminará automáticamente a la Linkedsección. Por defecto, la carpeta del paquete es, Frameworkspero puede cambiarla usando el Destinationcampo. Además, puede especificar a Subpath.

Dynamic linker :dylddurante la carga o el tiempo de ejecución intentará encontrar el marco incrustado usando @rpath[Acerca de] Si no se encuentra, se producirá el error [dyld: Biblioteca no cargada]

[Cuando use Enlace e Incrustar]

[Vocabulario]

yoAlex5
fuente