2011-08-01 20 views
11

Esta pregunta se ha hecho antes, pero al buscar en la documentación de las diversas herramientas de desarrollo, parece que es posible, simplemente no es obvio.Cómo crear una biblioteca estática para iOS sin hacer que todos los símbolos sean públicos

Motivo: Creación de una biblioteca estática para que otros desarrolladores de iOS la utilicen. Algunos símbolos en la biblioteca causarán problemas si se exportan, por lo que deseo convertirlos en símbolos solo internos. Con una biblioteca dinámica, esto es fácil, solo use el argumento -exported_symbols_listlibtool (ld) y enumere los que desea que sean públicos. La documentación libtool no permitirá este argumento para bibliotecas estáticas.

La biblioteca tiene varios archivos ObjectiveC .m que usan código entre sí. Solo se debe hacer pública una clase del grupo a los usuarios del último archivo de biblioteca estática .a.

Probado libtool -exported_symbols_list publicsymbols.exp pero el argumento libtool no es compatible con -static para bibliotecas estáticas.

No se pueden hacer los símbolos privados con atributos (si eso funciona) porque los necesitan los otros archivos .m del grupo.

parece ld puede tardar varios archivos .o y unirlos en un nuevo archivo .o (mediante el argumento -r) y que no tiene el descargo de responsabilidad "dinámica única" para el argumento -exported_symbols_list (que podría ser sólo documentación confusa ...).

simplemente como una prueba que construir mi proyecto con Xcode por lo que han hecho todos los archivos .o, y luego tratar de llamar ld en la línea de comandos, así:

ld -r -x -all_load -static -arch armv6 -syslibroot {path} 
    -filelist /Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCsdk.LinkFileList 
    -exported_symbols_list {exp file path} -o outputfile.o 

donde el {ruta} tipo cosas tienen largos caminos a los lugares apropiados allí.

pero tengo errores como el siguiente:

/usr/bin/ld_classic: /Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device. construir/objetos normales/ARMv6/ABCmain.o incompatibles, archivo contiene tipo no compatible de la sección 3 (_ TEXTO, _picsymbolstub4) en el comando de carga 0 (debe especificar "-dynamic" para ser utilizado)

por lo algo parece estar mal allí ...

¿Alguien sabe una manera inteligente de hacer que esto funcione? Gracias.

+0

¿Qué tipo de símbolos necesitas ocultar? – Macmade

+0

Símbolos que pueden entrar en conflicto si tienen la misma sub biblioteca ya vinculada a su aplicación (JSONkit dice). Puedo, obviamente, incluir los archivos JSONKit y decirles que los incluyan también si aún no están en su proyecto, pero esperaba que se agregara un archivo .h y .a al proyecto para una integración más limpia. . – Dad

Respuesta

14

Esto realmente no es posible, lamento decirlo. Tiene que ver con la forma en que funcionan las bibliotecas estáticas. Una biblioteca estática es poco más que un conjunto de archivos de objetos *.o agrupados, pero una biblioteca dinámica es una imagen binaria cargable, como un ejecutable.

Suponga que tiene cuatro archivos,

  • common.c define common, que es "privado"
  • fn1.c define fn1, que insta common.
  • fn2.c define fn2, que llama al common.
  • other.c define other.

En una biblioteca dinámica, el enlazador lía todo para arriba en un gran trozo de código. La biblioteca exporta other, fn1 y fn2. Tienes que cargar toda la biblioteca o nada de eso, pero dos programas pueden cargarlo sin poner varias copias en la memoria. El punto de entrada common simplemente falta en la tabla de símbolos; no puede llamarlo desde fuera de la biblioteca porque el enlazador no puede encontrarlo.

Tenga en cuenta que una aplicación y una biblioteca compartida tienen esencialmente el mismo formato: una aplicación es básicamente una biblioteca compartida que solo exporta un símbolo, main. (Esto no es exactamente cierto, pero está cerrado.)

En una biblioteca estática,, el vinculador nunca se ejecuta. Todos los archivos se compilan en archivos * .o y se guardan en un archivo de biblioteca * .a. Las referencias internas quedarán sin resolver.

Supongamos que su aplicación llama al fn1. El vinculador ve una llamada no resuelta al fn1, y luego mira a través de las bibliotecas. Encuentra una definición para fn1 en fn1.o. A continuación, el vinculador nota una llamada no resuelta al common, por lo que lo busca en common.o. Este programa no obtendrá el código de fn2.c u other.c, porque no usa las definiciones de esos archivos.

Las bibliotecas estáticas son muy antiguas y no tienen ninguna de las características de las bibliotecas dinámicas. Puede pensar en una biblioteca estática como básicamente un archivo comprimido lleno de código fuente compilado, a diferencia de una biblioteca dinámica que está vinculada entre sí. Nadie se molestó en extender el formato de archivo para agregar visibilidad de símbolos. Cuando se vincula con una biblioteca estática, obtiene el mismo resultado que si hubiera agregado el código fuente de la biblioteca a su programa.

La versión corta: Una biblioteca dinámica tiene una tabla de símbolos de todos los símbolos exportados, pero ninguno de los símbolos privados. De la misma manera, un archivo de objeto tiene una lista de todos sus símbolos extern, pero ninguno de los static. Pero una biblioteca estática no tiene tabla de símbolos, solo es un archivo. Por lo tanto, no existe un mecanismo para hacer que el código sea privado para una biblioteca estática (que no sea para definir los objetos static, pero eso no funciona para las clases Objective-C).

Si supiéramos por qué intentas hacer esto, quizás podamos darte una sugerencia. (¿Es por seguridad? Los conflictos de nombres? Todas estas preguntas tienen soluciones.)

+0

No quiero escribir una nueva respuesta, ya que han escrito una gran explicación aquí, pero parece la solución, entonces, sería combinar todos los archivos de código fuente en un archivo que se compila como una sola unidad. (Automáticamente, no manualmente.) El proyecto SQLite hace algo como esto. – benzado

+0

@benzado: Eso no funciona para las clases de Objective C. –

+0

Lo suficiente, por lo que incluso si pudiera ocultar otros símbolos (funciones, constantes), los nombres de las clases quedarían expuestos, por lo que no tiene sentido. – benzado

0

XCode BuildSetting puede hacer esto. 1. Conjunto Perform Single-Object Prelink-YES 2. Conjunto Exported Symbols File-path_for_symbols_file

tal vez usted debería eliminar -static, -exported_symbols_list no puede trabajar lib estática, pero puede tener efecto en el archivo objeto.

Cuestiones relacionadas