Как я могу избежать ошибок повторяющихся символов в xcode с общими статическими библиотеками?

У меня есть статические библиотеки A, B и C, организованные в проекты Xcode. A и B зависят от C. Когда я создаю проект iPhone, который зависит от A и B, я получаю сообщение об ошибке компоновщика, что в A и B обнаружен повторяющийся символ (из C). Как мне организовать эти три статические библиотеки, чтобы я можно ли включить их в другие проекты Xcode, не испытывая этой ошибки?


person richcollins    schedule 20.02.2010    source источник
comment
Конечно, при создании целевых библиотек для A и B вы должны включать только заголовки C. Вы будете ссылаться только на C при создании проекта iPhone?   -  person Max MacLeod    schedule 14.02.2013


Ответы (3)


Ответ Карла правильный, но по неправильным причинам: на самом деле нет ничего плохого в связывании статических библиотек вместе, как мы можем видеть, используя собственный образец Карла. Настройте образец кода Карла, а затем сделайте следующее: (я использую libtool, потому что это то, что использует 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$ 

Это связывает a2.a и b2.a с main.o. По словам Карла, это источник проблемы с OP, и app2 не должен связываться. Но, конечно, есть. Компоновщик достаточно умен, чтобы игнорировать два экземпляра одного и того же файла. Мы видим, что и a2.a, и b2.a содержат 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

Пока что ссылки нормально.

Я считаю, что проблема связана с универсальными двоичными файлами, либо универсальными двоичными файлами PPC / x86, либо универсальными двоичными файлами armv6 / armv7 iPhone. Проблема здесь в том, что есть ошибка с категориями и исправление (добавьте -all_load к флагам компоновщика) - это исправление, которое работает только для отдельных архитектур. Использование -all_load нарушает способность компоновщика игнорировать символы, определенные для нескольких архитектур, и возникает ошибка повторяющегося символа.

Я писал об этом здесь включая лучшее решение, чем использование -all_load.

person jamie    schedule 30.06.2010
comment
Вот рабочая ссылка на вашу запись в блоге: blog.binaryfinery.com / - person ThomasW; 31.03.2011
comment
Нет, эта ссылка тоже не работает. Это последний k, который продолжает удаляться. Ошибка с ТАК? Повторная попытка: binaryfinery.wordpress. ru / 2010/06/11 / - person Adam; 30.11.2013
comment
Это также происходит с Xcode 10 и использованием флага -ObjC вместо -all_load. - person Frederik; 14.11.2018

Альтернативой использованию -all_load является использование -force_load "path_to_lib" только для библиотек, где это необходимо. Например, вы можете использовать что-то вроде: -force_load "$(PROJECT_DIR)/libname".

Это позволяет избежать того, что вам нужно сделать для решения Джейми, которое требует от вас изменения файлов реализации.

Это решение, принятое проектом three20: http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df

изменить: начиная с Xcode 4.3 необходимость в -all_load и -force_load была удалена. Теперь нужно только -ObjC. Подробнее см. https://stackoverflow.com/a/2615407/211292.

person ThomasW    schedule 02.02.2011
comment
-all_load и -force_load больше не нужны, см. Здесь: stackoverflow.com/a/2615407/211292 - person ThomasW; 10.02.2016

Эта проблема не обязательно связана с Xcode или Objective-C. Не связывайте / не архивируйте библиотеки с другими библиотеками. A и B зависят от C только во время последней компоновки, а не при создании. Вы хотите:

  1. построить
  2. сборка B
  3. построить C
  4. создать приложение и ссылку

Вот пример проекта, который я сделал для демонстрации:

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

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;
}

Журнал сборки и запуска:

$ 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
person Carl Norum    schedule 20.02.2010
comment
Насколько я могу судить, Xcode не позволяет / не поддерживает это? Если это так, я думаю, вам следует исправить свой ответ, чтобы объяснить, как этого добиться (поскольку исходный вопрос помечен как xcode) - я пришел сюда из Google, потому что я не могу заставить Xcode справиться с этой простой настройкой! В противном случае этот ответ бесполезен, так как он ничего не делает для решения вопроса. - person Adam; 30.11.2013