¿Cuándo debemos usar "binarios incrustados" en lugar de "Marcos vinculados" en Xcode?
frameworks embedded-binary (3)
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 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
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.
Es parte de la gestión de
Dependency
[Acerca de]
Tenga en cuenta que
Xcode 11
contiene solo la sección
Frameworks, Libraries, and Embedded Content
en
General
pestaña
General
Enlace binario
Build Phases -> Link Binary With Libraries
es un espejo de
General -> Linked Frameworks and Libraries
.
Biblioteca estática y marco
Si agrega una
Static Library or Static Framework
a esta sección, aparecerá en el
grupo
Frameworks
y se agregará una referencia a su proyecto.
Luego será utilizado por
Static Linker
.
Static Linker
en tiempo de compilación
incluirá / copiará
todo el código de la biblioteca en el archivo de objeto ejecutable.
Static Library
-
Si no agrega una
static library
a esta sección, recibirá un error de enlazador [ld: símbolo (s) no encontrado (s)] . También elStatic linker
funciona en pareja conBuild Settings -> Library Search Paths
biblioteca [biblioteca no encontrada]
Framework
Debería funcionar con
Build Settings -> Framework Search Paths
[No existe tal módulo]
-
Si no agrega un
static framework
a esta sección, obtendrá un error de compilación [No existe tal módulo] . -
Puede omitir esta sección para
dynamic framework
.
Incrustar binario
Biblioteca estática y marco estático
Incrustar no tendría ningún sentido para una
Static Library
y un
Static Framework
porque los símbolos de ellos se compilan en el ejecutable.
Xcode no le permitirá colocar una
static library
en la sección Incrustar.
Marco Dinámico
Build Phases -> Embed Frameworks
es 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 sección
Embed
, se agregará / eliminará automáticamente a la sección
Linked
.
Por defecto, la carpeta del paquete es
Frameworks
pero puede cambiarla usando el campo
Destination
.
Además, puede especificar un
Subpath
.
Dynamic linker :dyld
en
carga o 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 usa Enlace e Incrustar]
[Vocabulario]
La fuente está aquí .
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 (por ejemplo, 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 vincularía al marco, sino que también lo incrustaría dentro de su paquete de aplicaciones 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, quizás con una llamada a
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 directorio
/bin
).
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 recursos integrados (es decir, no requiere que exista un marco), puede simplemente vincular con una biblioteca estática. Si encuentra que tiene varios módulos en su programa que desean usar el mismo código de biblioteca, entonces 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 archivos de encabezado y / o 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 imagen, aunque el archivo es en cambio una herramienta de línea de comandos ejecutable.
La función
popen()
(
man popen
desde su terminal para leer más sobre él) le permite ejecutar programas arbitrarios desde otro programa en ejecución.
La función
system()
es otra forma.
Hay otros, y daré un ejemplo histórico aquí que puede hacer que el uso de un binario incrustado sea un poco más claro:
Como probablemente ya 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 administrador predeterminado de usuario en el escritorio, al que se le asigna la identificación de usuario
501
.
En los sistemas operativos basados en Unix, solo el usuario
root
(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 usuario
root
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 ejecutarla como
root
.
La herramienta de línea de comando 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 al igual que cualquier otro archivo de recursos.
Cuando se le llama, el sistema operativo muestra un 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
root
en nombre de su aplicación.
Este proceso es similar a solo ejecutar un programa con
popen()
usted mismo, aunque
popen()
solo no le brinda el beneficio de la escalada de privilegios.