mundo - ¿Cómo creo una biblioteca dinámica(dylib) con Xcode?
xcode introduccion (4)
Estoy construyendo algunas utilidades de línea de comandos en Xcode (plain C, no Cocoa). Quiero que todos ellos utilicen mi versión personalizada de libpng, y quiero ahorrar espacio al compartir una copia de la biblioteca entre todos los ejecutables (no me importa volver a distribuir .dylib
con ellos).
¿Debo hacer algo de magia para obtener símbolos de exportación libpng?
¿El vínculo "Link Binary With Libraries" está establecido de forma estática?
Los documentos de Apple mencionan la carga de bibliotecas en tiempo de ejecución con dlopen
, pero ¿cómo puedo hacer que Xcode cree ejecutable sin quejarse de símbolos perdidos?
Creo que lo he descubierto:
libpng no se estaba enlazando correctamente, porque he creado ejecutables de 32/64 bits y una biblioteca de 32 bits. La configuración de compilación de la biblioteca y los ejecutables deben coincidir.
La configuración de libpng necesita tener toneladas de definiciones como
#define FEATURE_XXX_SUPPORTED
La fase de compilación "Enlace binario con bibliotecas" maneja bien las bibliotecas dinámicas, y la variable de entorno
DYLD_FALLBACK_LIBRARY_PATH
es necesaria para cargar.dylib
desde el paquete de aplicaciones.
Probablemente necesites asegurarte de que la biblioteca dinámica que crees tenga un archivo de símbolos exportado que enumere lo que se debe exportar de la biblioteca. Es solo una lista plana de los símbolos, uno por línea, para exportar.
Además, cuando se crea su biblioteca dinámica, recibe un nombre de instalación incrustado dentro de ella, que es, de forma predeterminada, la ruta en la que se genera. Posteriormente, cualquier elemento que esté vinculado a él lo buscará primero en la ruta especificada y luego buscará un conjunto (pequeño) de rutas predeterminadas que se describe en DYLD_FALLBACK_LIBRARY_PATH
en la página de dyld(1)
man dyld(1)
.
Si va a colocar esta biblioteca al lado de sus ejecutables, debe ajustar su nombre de instalación para hacer referencia a eso. Simplemente haciendo una búsqueda en Google para "nombre de instalación" debería aparecer una tonelada de información sobre cómo hacerlo.
Desafortunadamente, en mi experiencia, la documentación de Apple es anticuada, redundante y falta mucha información común que normalmente necesitarías.
Escribí un montón de cosas sobre esto en mi sitio web donde tuve que obtener FMOD (API de sonido) para trabajar con mi juego de plataforma cruzada que desarrollamos en la universidad. Es un proceso extraño y me sorprende que Apple no agregue más información sobre sus documentos de desarrollador.
Desafortunadamente, por "malvado" que sea Microsoft, en realidad hacen un trabajo mucho mejor al cuidar de sus desarrolladores con documentación (esto viene de un evangelista de Apple).
Básicamente, lo que no estás haciendo es DESPUÉS de haber compilado tu paquete .app. Luego debe ejecutar un comando en el ejecutable binario /MyApp.app/contents/MacOS/MyApp para cambiar el lugar donde el ejecutable busca su archivo de biblioteca. Debe crear una nueva fase de compilación que pueda ejecutar un script. No voy a explicar este proceso nuevamente, ya lo he hecho en profundidad aquí:
http://brockwoolf.com/blog/how-to-use-dynamic-libraries-in-xcode-31-using-fmod
Espero que esto ayude.
¿Conoce la página de referencia de Apple, Temas de programación de la biblioteca dinámica ? Debe cubrir la mayor parte de lo que necesita. Tenga en cuenta que hay bibliotecas compartidas que se cargan incondicionalmente al inicio del programa y las bibliotecas cargadas dinámicamente (paquetes, IIRC) que se cargan a pedido, y las dos son algo diferentes en MacOS X de los equivalentes en Linux o Solaris.
Enlace dinámico en Mac OS X, un pequeño ejemplo
Pasos:
- crear una biblioteca libmylib.dylib que contenga mymod.o
- compila y enlaza un "callmymod" que lo llama
- llame a mymod desde callmymod, usando DYLD_LIBRARY_PATH y DYLD_PRINT_LIBRARIES
Problema: "solo" desea crear una biblioteca para que otros módulos la utilicen. Sin embargo, existe una abrumadora cantidad de programas: gcc, ld, macosx libtool, dyld, con un montón de opciones, un compost bien descompuesto y diferencias entre MacOSX y Linux. Hay toneladas de páginas man (cuento 7679 + 1358 + 228 + 226 líneas en 10.4.11 ppc) pero no hay muchos ejemplos, o programas con el modo "dime lo que estás haciendo".
(Lo más importante para entender es hacer una VISIÓN GENERAL simplificada para usted: dibujar algunas imágenes, ejecutar algunos ejemplos pequeños, explicárselo a otra persona).
Antecedentes: apple OverviewOfDynamicLibraries , Wikipedia Dynamic_library
Paso 1, crea libmylib.dylib -
mymod.c:
#include <stdio.h>
void mymod( int x )
{
printf( "mymod: %d/n", x );
}
gcc -c mymod.c # -> mymod.o
gcc -dynamiclib -current_version 1.0 mymod.o -o libmylib.dylib
# calls libtool with many options -- see man libtool
# -compatibility_version is used by dyld, see also cmpdylib
file libmylib.dylib # Mach-O dynamically linked shared library ppc
otool -L libmylib.dylib # versions, refs /usr/lib/libgcc_s.1.dylib
Paso 2, compila y enlaza callmymod -
callmymod.c:
extern void mymod( int x );
int main( int argc, char** argv )
{
mymod( 42 );
}
gcc -c callmymod.c
gcc -v callmymod.o ./libmylib.dylib -o callmymod
# == gcc callmymod.o -dynamic -L. -lmylib
otool -L callmymod # refs libmylib.dylib
nm -gpv callmymod # U undef _mymod: just a reference, not mymod itself
Paso 3, ejecuta callmymod vinculando a libmylib.dylib -
export DYLD_PRINT_LIBRARIES=1 # see what dyld does, for ALL programs
./callmymod
dyld: loaded: libmylib.dylib ...
mymod: 42
mv libmylib.dylib /tmp
export DYLD_LIBRARY_PATH=/tmp # dir:dir:...
./callmymod
dyld: loaded: /tmp/libmylib.dylib ...
mymod: 42
unset DYLD_PRINT_LIBRARIES
unset DYLD_LIBRARY_PATH
Eso termina un pequeño ejemplo; Espero que ayude a entender los pasos.
(Si haces esto mucho, mira GNU Libtool que es glibtool en macs y SCons ).
aclamaciones
- denis