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更好的解决方案.
这个问题不一定与Xcode或Objective-C有关.不要将库链接/存档到其他库中.A&B仅在最终链接时依赖于C,而不是在它们构建时.你要:
这是我用来演示的示例项目:
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)
使用的另一种方法-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/.