如何解决与gcc链接的“多个已定义符号”
问题描述:
我使用的是具有gcc 2.95.3的旧系统,我必须链接两个对象,尽管它们之间没有任何关系,但它们每个都有类似命名的方法。我不能重命名其中的任何一个,但我希望有一种方法可以构建它们,以免连接器发生抱怨。它所抱怨的方法都是由对象内部的类在内部调用的。我能做什么?如何解决与gcc链接的“多个已定义符号”
答
如果你有一个完整的GNU工具链,你应该能够解决使用objcopy
,这样你的问题(如果我理解正确的话您的问题):
这里有两个非常相似的对象,“富“和‘酒吧’,这两个出口一个名为clash
符号 - 这是内部使用,但并不真的需要在所有出口:
$ cat foo.c
#include <stdio.h>
void clash(char *s) { printf("foo: %s\n", s); }
void foo(char *s) { clash(s); }
$
和
$ cat bar.c
#include <stdio.h>
void clash(char *s) { printf("bar: %s\n", s); }
void bar(char *s) { clash(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 `clash':
bar.c:(.text+0x0): multiple definition of `clash'
foo.o:foo.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
$
因此,使用objcopy
改变一个clash
的可见性(或如果你喜欢!)的对象:
$ objcopy --localize-symbol=clash bar.o bar2.o
$
现在你可以成功链接修改后的对象 - 并且程序的行为如同它应该:
$ gcc -o test main.o foo.o bar2.o
$ ./test
foo: Hello
bar: world
$
如何在指定本地对象之前指定对象?在代码理想情况下,也可能作为对象编译的一部分? – CptanPanic 2010-07-19 14:55:09
如果碰撞函数仅用于单个文件中,则根本不需要导出它,因此使其成为“静态”应该可以工作。这将与我上面的小例子一起工作。 (我认为你不能改变原始源代码,而需要使用对象来处理,而当你说你不能重命名的时候)。如果你需要在早期的链接阶段为对象之间的引用导出这些符号(例如,链接部分对象或库),那么事情就会变得更加困难,并且将其排序取决于构建过程的更精细的细节。 – 2010-07-19 20:02:32