2011-09-27 7 views
16

He creado un nuevo framework de cacao en Xcode, eliminé todas las bibliotecas y archivos que incluye al principio, excepto los archivos de apoyo.Cómo creo un marco de trabajo con archivos dylib en Xcode 4

tengo 2 archivos:

add.h 

#ifndef add_add_h 
#define add_add_h 

void add(void); 

#endif 

y

add.c 
#include <stdio.h> 
#include "add.h" 

void add(void) 
{ 
    printf("adfding"); 

} 

en las fases de construcción añado add.c para compilar las fuentes y add.h para compilar los encabezados públicas. El proyecto se compila sin problemas, pero en el marco no hay ningún archivo dylib y cuando arrastro y coloco el marco en otro proyecto, dice que el archivo dylib no se pudo encontrar.

dyld: Library not loaded: @rpath/add.framework/Versions/A/add 
    Referenced from: /Users/vjoukov/Desktop/Projects/test/build/Debug/test.app/Contents/MacOS/test 
    Reason: image not found 

¿Cómo puedo hacer una estructura simple y mantener archivos dylib dentro de ella?

Respuesta

61

Creo que está malinterpretando el mensaje de error.

A .framework funciona como una biblioteca dinámica, pero no habrá ningún archivo de objeto cargable Mach-O con una extensión de nombre de archivo .dylib dentro de la carpeta .framework.

Hay un par de razones por las que puede recibir el mensaje de error dyld, el cargador de la biblioteca de enlace dinámico, en tiempo de ejecución. La primera es que olvidó copiar .frameworks en el paquete de aplicaciones creado durante el proceso de compilación. Si bien se pueden copiar en cualquier ubicación dentro del paquete de la aplicación, el lugar tradicional se encuentra en AppName.app/Contents/Frameworks/. Si aún no lo ha hecho, elija Proyecto> Nueva fase de compilación> Nueva copia de la fase de compilación de archivos. Cambie la ventana emergente de Destino a Frameworks como en la imagen de abajo.

enter image description here

A continuación, arrastre el icono del marco en la carpeta para que se copia durante el proceso de construcción.

enter image description here

La segunda y más probable razón, el marco no se puede encontrar en tiempo de ejecución es que no se ha especificado ninguna ruta de búsqueda RUNPATH para su ejecutable principal. (Esto es necesario, porque, como vimos en su mensaje de error, su marco se construyó utilizando el nombre de instalación de estilo @rpath/ más reciente (@rpath/add.framework/Versions/A/add) en lugar de los estilos anteriores @executable_path/ o @loader_path/).

Siempre que copie los marcos personalizados a la ubicación mencionada anteriormente, deberá añadir una entrada de ruta de búsqueda de RUNPATH @loader_path/../Frameworks, como se muestra en la siguiente imagen:

enter image description here

El siguiente extracto que explica cómo bibliotecas dinámicas se encuentran en tiempo de ejecución es de la página de manual de dyld:

biblioteca dinámica CARGA

A diferencia de muchos otros sistemas operativos, Darwin no ubica las bibliotecas dinámicas dependientes a través de su nombre de archivo de hoja. En cambio, se usa la ruta completa de a cada dylib (p. /usr/lib/libSystem.B.dylib). Pero hay veces cuando una ruta completa no es apropiada; por ejemplo, puede desear que sus binarios sean instalable en cualquier lugar del disco. Para respaldar eso, hay tres variables @xxx/ que se pueden usar como un prefijo de ruta. En el tiempo de ejecución dyld sustituye una ruta generada dinámicamente para el prefijo @xxx/.

@executable_path/

Esta variable se reemplaza con la ruta de acceso al directorio de que contiene el ejecutable principal para el proceso. Esto es útil para cargando dylibs/frameworks incrustados en un directorio .app. Si el archivo ejecutable principal está en /some/path/My.app/Contents/MacOS/My y un archivo marco dylib está en
/some/path/My.app/Contents/Frameworks/Foo.framework/Versions/A/Foo, entonces el camino de carga marco podría codificarse como @executable_path/../Frameworks/Foo.framework/Versions/A/Foo y el directorio .app podría puede mover alrededor en el sistema de archivos y dyld todavía podrá cargar el marco incrustado.

@loader_path/

Esta variable se reemplaza con la ruta de acceso al directorio que contiene el mach-o binario que contiene el comando de carga usando @loader_path. Por lo tanto, en cada binario, @loader_path se resuelve en una ruta diferente , mientras que @executable_path siempre se resuelve en la misma ruta . @loader_path es útil como la ruta de carga para un framework/dylib incrustado en un plug-in, si el sistema de archivos final ubicación del complemento desconocido (por lo que las rutas absolutas no pueden usarse) o si se utiliza el complemento por múltiples aplicaciones (para que @executable_path no se pueda usar). Si el plug-in de archivos mach-o está en /some/path/Myfilter.plugin/Contents/MacOS/Myfilter y un archivo dylib marco está en /some/path/Myfilter.plugin/Contents/Frameworks/Foo.framework/Versions/A/Foo, entonces el camino de carga marco podría codificarse como @loader_path/../Frameworks/Foo.framework/Versions/A/Foo y el directorio Myfilter.plugin podría ser se trasladaron por el archivo sistema y dyld todavía será capaz de cargar el marco incrustado.

@rpath/

dyld mantiene una pila actual de caminos llamado el Trayecto de lista. Cuando se encuentra @rpath, se sustituye con cada ruta en la lista de ruta de ejecución hasta que se encuentre un dylib cargable. La pila de la ruta de ejecución se genera a partir de los comandos de carga LC_RPATH en la cadena de dependencias que conduce a la carga actual de dylib. Puede agregar un comando de carga LC_RPATH a una imagen con la opción -rpath a ld (1). Incluso puede agregar una ruta de comandos de carga de LC_RPATH que comienza con @loader_path/, e insertará una ruta en la pila de ruta de ejecución que se relaciona con la imagen que contiene el LC_RPATH. El uso de @rpath es más útil cuando se tiene una compleja estructura directorio de programas y dylibs que se pueden instalar en cualquier lugar , pero mantener sus posiciones relativas. Este escenario podría implementarse utilizando @loader_path, pero cada cliente de un dylib pudiera hacer falta un camino de carga diferente porque su relación posición en el sistema de archivos es diferente. El uso de @rpath introduce un nivel de indirección que simplifica las cosas. Usted elija una ubicación en su estructura de directorio como punto de anclaje. Cada dylib a continuación, obtiene una ruta de instalación que se inicia con @rpath y es la ruta de acceso al dylib con relación al punto de anclaje. Cada ejecutable principal está vinculado con -rpath @loader_path/zzz, donde zzz es la ruta del ejecutable al punto de anclaje. En tiempo de ejecución dyld conjuntos correr camino a ser el punto de anclaje, entonces cada dylib es encontrado con relación al punto de anclaje.

+5

WOW! Esa es una diablos de una respuesta completa, ¡también resolvió un problema que estaba teniendo! ¡¡Gracias!! –

+0

Respuesta muy completa y completa ... ¡Buen trabajo! –

+0

¡Respuesta perfecta! Nunca supe cómo funcionó. ¡Bonito! – JackPearse

Cuestiones relacionadas