c objective-c xcode duplicate-symbol

¿Cómo puedo evitar los errores de "símbolo duplicado" en xcode con bibliotecas estáticas compartidas?



objective-c duplicate-symbol (3)

Tengo bibliotecas estáticas A, B y C organizadas en proyectos Xcode. A y B dependen de C. Cuando construyo un proyecto de iPhone que depende de A y B, recibo un error de enlace que indica que se detectó un símbolo duplicado (de C) en A y B. ¿Cómo puedo organizar estas tres bibliotecas estáticas? ¿Se pueden incluir en otros proyectos de Xcode sin experimentar este error?


Este problema no está necesariamente relacionado con Xcode o Objective-C. No vincule / archive bibliotecas en otras bibliotecas. A y B solo dependen de C en el momento del enlace final, no cuando se construyen. Usted quiere:

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

Aquí hay un proyecto de ejemplo que hice para demostrar:

Makefile:

app: main.o a.a b.a c.a gcc $^ -o $@ %.o: %.c gcc -Wall -c $^ %.a: %.o ar -r $@ $^ clean: rm -rf *.o *.a app

C.A:

#include <stdio.h> void c(void); void a(void) { printf("a/n"); c(); }

antes de Cristo:

#include <stdio.h> void c(void); void b(void) { printf("b/n"); c(); }

cc:

#include <stdio.h> void c(void) { printf("c/n"); }

C Principal:

#include <stdio.h> void a(void); void b(void); int main(int argc, char *argv[]) { a(); b(); return 0; }

Crear 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


La respuesta de Carl es correcta, pero por los motivos equivocados: en realidad no hay nada de malo en vincular bibliotecas estáticas, como podemos ver usando el propio ejemplo de Carl. Configure el código de muestra de Carl y luego haga esto: (Yo uso libtool porque eso es lo que usa 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$

Esto enlaza a2.a y b2.a con main.o. Según Carl, esta es la fuente del problema de los OP, y la aplicación 2 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 co:

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, se vincula bien.

El problema está, creo, vinculado a los binarios universales, ya sea los binarios universales PPC / x86, o los binarios universales de armv6 / armv7 para iPhone. El problema aquí es que hay un error con las categories y la solución (agregar -todos -cargar a las banderas del vinculador) es una solución que solo funciona para arquitecturas individuales. El uso de -all_load rompe la capacidad de los enlazadores para ignorar los símbolos definidos para múltiples arquitecturas, y tiene su error de símbolo duplicado.

Escribí sobre esto here incluyendo una mejor solución que usar -all_load.


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

Esto evita lo que debe 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: a partir de Xcode 4.3 se -all_load la necesidad de -all_load y -force_load . Ahora solo se necesita -ObjC . Consulte https://.com/a/2615407/211292 para obtener más detalles.