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

时间:2010-02-20 03:08:54

标签: c objective-c xcode duplicate-symbol

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

3 个答案:

答案 0 :(得分: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$ 

这将a2.a和b2.a与main.o相关联。根据Carl的说法,这是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通用二进制文件。这里的问题是categories存在一个错误,修复(添加-all_load到链接器标志)是一个仅适用于单一体系结构的修复程序。使用-all_load会破坏链接器忽略为多个体系结构定义的符号的能力,并且您有重复的符号错误。

我写了here,包括比使用-all_load更好的解决方案。

答案 1 :(得分:6)

此问题不一定与Xcode或Objective-C相关。不要将库链接/存档到其他库中。 A& B仅在最终链接时依赖于C,而不是在它们构建时。你想要:

  1. 建立A
  2. 构建B
  3. build C
  4. 构建app&链路
  5. 这是我演示的一个示例项目:

    生成文件:

    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
    

    交流转换器:

    #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
    

答案 2 :(得分: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。有关详细信息,请参阅https://stackoverflow.com/a/2615407/211292