如何使用共享静态库避免xcode中的"重复符号"错误?

ric*_*ins 29 c xcode objective-c duplicate-symbol

我有静态库A,B和C组织到Xcode项目中.A和B依赖于C.当我构建一个依赖于A和B的iPhone项目时,我得到一个链接器错误,在A和B中检测到重复的符号(来自C).我如何组织这三个静态库,所以我可以将它们包含在其他Xcode项目中而不会遇到此错误?

jam*_*mie 26

Carl的答案是正确的,但出于错误的原因:将静态库链接在一起并没有什么问题,正如我们可以看到使用Carl自己的样本.设置Carl的示例代码然后执行此操作:(我使用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$ 
Run Code Online (Sandbox Code Playgroud)

这将a2.a和b2.a与main.o相关联.根据Carl的说法,这是OP问题的根源,app2不应该链接.但当然可以.链接器足够智能,可以忽略同一文件的两个实例.我们可以看到a2.a和b2.a都包含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
Run Code Online (Sandbox Code Playgroud)

但它很好.

我认为,问题在于通用二进制文件,无论是PPC/x86通用二进制文件,还是armv6/armv7 iPhone通用二进制文件.这里的问题是类别存在错误,修复(将-all_load添加到链接器标志)是一种仅适用于单一体系结构的修复.使用-all_load会破坏链接器忽略为多个体系结构定义的符号的能力,并且您有重复的符号错误.

在这里写了一些包括比使用-all_load更好的解决方案.

  • 这是您博客条目的工作链接:http://blog.binaryfinery.com/universal-static-library-problem-in-iphone-sd (2认同)

Car*_*rum 6

这个问题不一定与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
Run Code Online (Sandbox Code Playgroud)

AC:

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

void a(void)
{
  printf("a\n");
  c();
}
Run Code Online (Sandbox Code Playgroud)

公元前:

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

void b(void)
{
  printf("b\n");
  c();
}
Run Code Online (Sandbox Code Playgroud)

抄送:

#include <stdio.h>

void c(void)
{
  printf("c\n");
}
Run Code Online (Sandbox Code Playgroud)

main.c中:

#include <stdio.h>

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

int main(int argc, char *argv[])
{
  a();
  b();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

构建并运行日志:

$ 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
Run Code Online (Sandbox Code Playgroud)


Tho*_*asW 6

使用的另一种方法-all_load-force_load仅对需要它的库使用"path_to_lib".例如,您可以使用以下内容:-force_load "$(PROJECT_DIR)/libname".

这避免了您需要为Jamie的解决方案做的事情,这需要您修改实现文件.

这是three20项目采用的解决方案:http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df

编辑:从Xcode 4.3开始,需要-all_load-force_load已被删除.现在只-ObjC需要.有关详细信息,请参阅/sf/answers/183078521/.