如何解决与gcc链接的“多个已定义符号”

问题描述:

我使用的是具有gcc 2.95.3的旧系统,我必须链接两个对象,尽管它们之间没有任何关系,但它们每个都有类似命名的方法。我不能重命名其中的任何一个,但我希望有一种方法可以构建它们,以免连接器发生抱怨。它所抱怨的方法都是由对象内部的类在内部调用的。我能做什么?如何解决与gcc链接的“多个已定义符号”

如果你有一个完整的GNU工具链,你应该能够解决使用objcopy,这样你的问题(如果我理解正确的话您的问题):

这里有两个非常相似的对象,“富“和‘酒吧’,这两个出口一个名为*符号 - 这是内部使用,但并不真的需要在所有出口:

$ cat foo.c 
#include <stdio.h> 
void *(char *s) { printf("foo: %s\n", s); } 
void foo(char *s) { *(s); } 
$ 

$ cat bar.c 
#include <stdio.h> 
void *(char *s) { printf("bar: %s\n", s); } 
void bar(char *s) { *(s); } 
$ 

而这里的主代码,其希望同时使用:

$ cat main.c 
extern void foo(char *s); 
extern void bar(char *s); 

int main(void) 
{ 
    foo("Hello"); 
    bar("world"); 
    return 0; 
} 
$ 

链接在一起不起作用:

$ gcc -Wall -c foo.c 
$ gcc -Wall -c bar.c 
$ gcc -Wall -c main.c 
$ gcc -o test main.o foo.o bar.o 
bar.o: In function `*': 
bar.c:(.text+0x0): multiple definition of `*' 
foo.o:foo.c:(.text+0x0): first defined here 
collect2: ld returned 1 exit status 
$ 

因此,使用objcopy改变一个*的可见性(或如果你喜欢!)的对象:

$ objcopy --localize-symbol=* bar.o bar2.o 
$ 

现在你可以成功链接修改后的对象 - 并且程序的行为如同它应该:

$ gcc -o test main.o foo.o bar2.o 
$ ./test 
foo: Hello 
bar: world 
$ 
+1

如何在指定本地对象之前指定对象?在代码理想情况下,也可能作为对象编译的一部分? – CptanPanic 2010-07-19 14:55:09

+2

如果碰撞函数仅用于单个文件中,则根本不需要导出它,因此使其成为“静态”应该可以工作。这将与我上面的小例子一起工作。 (我认为你不能改变原始源代码,而需要使用对象来处理,而当你说你不能重命名的时候)。如果你需要在早期的链接阶段为对象之间的引用导出这些符号(例如,链接部分对象或库),那么事情就会变得更加困难,并且将其排序取决于构建过程的更精细的细节。 – 2010-07-19 20:02:32