C语言 如何使用共享静态库避免 xcode 中的“重复符号”错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2300867/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I avoid "duplicate symbol" errors in xcode with shared static libraries?
提问by richcollins
I have static libraries A, B and C organized into Xcode projects. A and B depend on C. When I build an iPhone project that depends on A and B, I get a linker error that a duplicate symbol (from C) was detected in A and B. How can I organize these three static libraries so I can include them in other Xcode projects without experiencing this error?
我将静态库 A、B 和 C 组织到 Xcode 项目中。A 和 B 依赖于 C。当我构建一个依赖于 A 和 B 的 iPhone 项目时,我收到一个链接器错误,即在 A 和 B 中检测到重复符号(来自 C)。我该如何组织这三个静态库,以便我可以将它们包含在其他 Xcode 项目中而不会遇到此错误吗?
回答by jamie
Carl's answer is right, but for the wrong reasons: there's actually nothing wrong with linking static libraries together, as we can see using Carl's own sample. Set-up Carl's sample code and then do this: (I use libtool because that is what XCode uses)
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$
This links a2.a and b2.a with main.o. According to Carl, this is the source of OPs problem, and app2 shouldn't link. But of course it does. The linker is smart enough to ignore two instances of the same file. We can see that both a2.a and b2.a contain c.o:
这将 a2.a 和 b2.a 与 main.o 联系起来。根据 Carl 的说法,这是 OPs 问题的根源,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
Yet it links fine.
但它链接良好。
The problem is, I believe, linked to Universal Binaries, either PPC/x86 universal binaries, or armv6/armv7 iPhone universal binaries. The problem here is that there is a bug with categoriesand the fix (add -all_load to the linker flags) is a fix that only works for single architectures. Using -all_load breaks the linkers ability to ignore symbols that are defined for multiple architectures, and you have your duplicate symbol error.
我相信问题是与通用二进制文件相关联,要么是 PPC/x86 通用二进制文件,要么是 armv6/armv7 iPhone 通用二进制文件。这里的问题是类别存在错误,修复(将 -all_load 添加到链接器标志)是仅适用于单一架构的修复。使用 -all_load 会破坏链接器忽略为多个体系结构定义的符号的能力,并且您会遇到重复符号错误。
I wrote about it hereincluding a better solution than using -all_load.
我在这里写了一个比使用 -all_load 更好的解决方案。
回答by ThomasW
A alternative to using -all_loadis to use -force_load"path_to_lib" just for the libraries where it is needed. For example, you can use something like: -force_load "$(PROJECT_DIR)/libname".
使用的替代方法-all_load是将-force_load“path_to_lib”仅用于需要它的库。例如,你可以使用这样的:-force_load "$(PROJECT_DIR)/libname"。
This avoids what you need to do for Jamie's solution which requires you to modify implementation files.
这避免了您需要为 Jamie 的解决方案执行的操作,该解决方案需要您修改实现文件。
This is the solution adopted by the three20 project: http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df
这是three20项目采用的解决方案:http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df
edit:as of Xcode 4.3 the need for -all_loadand -force_loadhas been removed. Now only -ObjCis needed. See https://stackoverflow.com/a/2615407/211292for more details.
编辑:从 Xcode 4.3 开始,需要-all_load和-force_load已被删除。现在只-ObjC需要。有关更多详细信息,请参阅https://stackoverflow.com/a/2615407/211292。
回答by Carl Norum
This problem isn't necessarily Xcode or Objective-C related. Don't link/archive libraries into other libraries. A & B only depend on C at final link time, not when they're built. You want:
这个问题不一定与 Xcode 或 Objective-C 相关。不要将库链接/归档到其他库中。A & B 仅在最终链接时依赖于 C,而不是在构建时。你要:
- build A
- build B
- build C
- build app & link
- 建个
- 建造B
- 构建 C
- 构建应用程序和链接
Here's an example project I made to demonstrate:
这是我用来演示的示例项目:
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;
}
Build and run log:
构建和运行日志:
$ 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

