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

5 minutos de lectura

avatar de usuario
ricocollins

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, aparece un error del enlazador que indica que se detectó un símbolo duplicado (de C) en A y B. ¿Cómo puedo organizar estas tres bibliotecas estáticas para ¿Puede incluirlos en otros proyectos de Xcode sin experimentar este error?

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

    –Max MacLeod

    14 de febrero de 2013 a las 9:43

avatar de usuario
Jaime

La respuesta de Carl es correcta, pero por las razones equivocadas: en realidad no hay nada de malo en vincular bibliotecas estáticas, como podemos ver usando la propia muestra 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 vincula a2.a y b2.a con main.o. Según Carl, esta es la fuente del problema de los 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 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, enlaza bien.

Creo que el problema está relacionado con los binarios universales, ya sean binarios universales PPC/x86 o binarios universales armv6/armv7 iPhone. El problema aquí es que hay un error con categorías y la solución (agregar -all_load a las banderas del enlazador) 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 que están definidos para múltiples arquitecturas, y tiene su error de símbolo duplicado.

escribí sobre eso aquí incluyendo una mejor solución que usar -all_load.

  • Aquí hay un enlace de trabajo a su entrada de blog: blog.binaryfinery.com/…

    – ThomasW

    31 de marzo de 2011 a las 15:10

  • No, ese enlace también está roto. Es la “k” final la que sigue siendo eliminada. Error con SO? Intentando otra vez: binaryfinery.wordpress.com/2010/06/11/…

    – Adán

    30 de noviembre de 2013 a las 16:58

  • Esto también sucede con Xcode 10 y usando el -ObjC bandera en lugar de -all_load.

    – Federico

    14 de noviembre de 2018 a las 14:15

avatar de usuario
ThomasW

Una alternativa al uso -all_load es usar -force_load “path_to_lib” solo para las bibliotecas donde se necesita. Por ejemplo, puedes 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/tres20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df

editar: a partir de Xcode 4.3 la necesidad de -all_load y -force_load ha sido removido. Solo ahora -ObjC se necesita Consulte https://stackoverflow.com/a/2615407/211292 para obtener más detalles.

  • -all_load y -force_load ya no son necesarios, consulte aquí: stackoverflow.com/a/2615407/211292

    – ThomasW

    10 de febrero de 2016 a las 1:12

avatar de usuario
carl norum

Este problema no está necesariamente relacionado con Xcode o Objective-C. No enlace/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. crear 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 [email protected]

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

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

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

  • Por lo que puedo decir, ¿Xcode no permite/admite esto? Si es así, creo que debería corregir su respuesta para explicar cómo lograrlo (ya que la pregunta original está etiquetada como “xcode”). ¡Vine aquí desde 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.

    – Adán

    30 de noviembre de 2013 a las 16:56

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad