2010-02-20 18 views
29

Tengo bibliotecas estáticas A, B y C organizadas en proyectos de Xcode. A y B dependen de C. Cuando construyo un proyecto de iPhone que depende de A y B, aparece un error de enlazador al detectar un símbolo duplicado (de C) en A y B. ¿Cómo puedo organizar estas tres bibliotecas estáticas para que yo pueda puede incluirlos en otros proyectos de Xcode sin experimentar este error?¿Cómo puedo evitar errores de "símbolo duplicado" en xcode con bibliotecas estáticas compartidas?

+0

seguramente al compilar los objetivos de la biblioteca para A y B, solo debe incluir los encabezados de C. ¿Solo vincularía con C al crear el proyecto de iPhone? –

Respuesta

6

Este problema no es necesariamente relacionado con Xcode o Objective-C. No enlace/archive bibliotecas en otras bibliotecas. A & B solo depende de C en el tiempo del enlace final, no cuando están construidos. ¿Quieres:

  1. construir un
  2. acumulación B
  3. acumulación C
  4. aplicación acumulación & enlace

He aquí un ejemplo de proyecto que hice para demostrar:

Makefile:

app: main.o a.a b.a c.a 
     gcc $^ -o [email protected] 

%.o: %.c 
     gcc -Wall -c $^ 

%.a: %.o 
     ar -r [email protected] $^ 

clean: 
     rm -rf *.o *.a app 

A.C.:

#include <stdio.h> 
void c(void); 

void a(void) 
{ 
    printf("a\n"); 
    c(); 
} 

b.c:

#include <stdio.h> 
void c(void); 

void b(void) 
{ 
    printf("b\n"); 
    c(); 
} 

C.C:

#include <stdio.h> 

void c(void) 
{ 
    printf("c\n"); 
} 

main.c:

#include <stdio.h> 

void a(void); 
void b(void); 

int main(int argc, char *argv[]) 
{ 
    a(); 
    b(); 
    return 0; 
} 

generar y ejecutar registro:

$ make 
gcc -Wall -c main.c 
gcc -Wall -c a.c 
ar -r a.a a.o 
ar: creating archive a.a 
gcc -Wall -c b.c 
ar -r b.a b.o 
ar: creating archive b.a 
gcc -Wall -c c.c 
ar -r c.a c.o 
ar: creating archive c.a 
gcc main.o a.a b.a c.a -o app 
rm a.o b.o c.o 
$ ./app 
a 
c 
b 
c 
+0

Por lo que puedo ver, Xcode no permite/admite esto? Si lo hace, creo que debes corregir tu respuesta para explicar cómo lograrlo (ya que la pregunta original está etiquetada como "xcode") - Vine aquí de Google porque no puedo hacer que Xcode maneje esta configuración simple. Si no, esta respuesta es inútil, ya que no hace nada para resolver la pregunta. – Adam

25

La respuesta de Carl es correcta, pero por las razones equivocadas: no hay nada de malo en vincular bibliotecas estáticas, como podemos ver con la propia muestra de Carl. Set-up código de ejemplo de Carl y luego hacer esto: (yo uso libtool porque eso es lo utiliza XCode)

neutron:libtest jamie$ libtool -o a2.a a.a c.a 
neutron:libtest jamie$ libtool -o b2.a b.a c.a 
neutron:libtest jamie$ gcc main.o a2.a b2.a -o app2 
neutron:libtest jamie$ ./app2 
a 
c 
b 
c 
neutron:libtest jamie$ 

Estos links A2.a y b2.a con main.o. Según Carl, esta es la fuente del problema de OP, y app2 no debería vincularse. Pero por supuesto que sí. El enlazador es lo suficientemente inteligente como para ignorar dos instancias del mismo archivo. Podemos ver que tanto a2.a como b2.a contienen c.o:

neutron:libtest jamie$ ar -t a2.a 
__.SYMDEF SORTED 
a.o 
c.o 
neutron:libtest jamie$ ar -t b2.a 
__.SYMDEF SORTED 
b.o 
c.o 

Sin embargo, enlaza bien.

El problema es que, creo, está relacionado con los binarios universales, ya sean binarios universales PPC/x86 o binarios universales de armv6/armv7. El problema aquí es que hay un error con categories y la solución (add -all_load a los indicadores del enlazador) es una corrección que solo funciona para arquitecturas únicas. El uso de -all_load rompe la capacidad de los enlazadores de ignorar los símbolos que están definidos para múltiples arquitecturas, y usted tiene el error de símbolo duplicado.

Escribí al respecto here incluyendo una mejor solución que usar -all_load.

+2

Aquí hay un enlace de trabajo a su entrada de blog: http://blog.binaryfinery.com/universal-static-library-problem-in-iphone-sd – ThomasW

+0

No, ese enlace también está roto. Es la "k" final que sigue siendo eliminada. ¿Error con SO? Probando nuevamente: http://binaryfinery.wordpress.com/2010/06/11/universal-static-library-problem-in-iphone-sdk/ – Adam

6

Una alternativa al uso de -all_load es utilizar -force_load "path_to_lib" solo para las bibliotecas donde se necesita. Por ejemplo, puede usar algo como: -force_load "$(PROJECT_DIR)/libname".

Esto evita lo que necesita hacer para la solución de Jamie, que requiere que modifique los archivos de implementación.

Esta es la solución adoptada por el proyecto Three20: http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df

edición: como de Xcode 4.3 la necesidad de -all_load y -force_load ha sido eliminado. Ahora solo se necesita -ObjC. Ver https://stackoverflow.com/a/2615407/211292 para más detalles.

+1

¿Alguna actualización para Xcode 4.3? – Klaas

+0

'-all_load' y' -force_load' ya no son necesarios, mira aquí: http://stackoverflow.com/a/2615407/211292 – ThomasW

Cuestiones relacionadas