如何在与gcc链接时绕过"多个定义的符号"

Cpt*_*nic 5 linker gcc qnx ld

我使用的是一个具有gcc 2.95.3的旧系统,我必须链接两个对象,虽然它们彼此无关,但它们每个都有类似命名的方法.我不能重命名它们中的任何一个,但我希望有一种方法来构建它们,以免链接器抱怨.它所抱怨的方法都是由对象内的类内部调用的.我能做什么?

Mat*_*ery 9

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

这里有两个非常相似的对象,"foo"和"bar",它们都导出一个名为的符号clash- 在内部使用,但根本不需要导出:

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

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

这是主要代码,它想要使用两者:

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

int main(void)
{
    foo("Hello");
    bar("world");
    return 0;
}
$ 
Run Code Online (Sandbox Code Playgroud)

将它们链接在一起不起作用:

$ 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
$ 
Run Code Online (Sandbox Code Playgroud)

因此,用于objcopy更改对象clash中的一个(或两者,如果您喜欢!)的可见性:

$ objcopy --localize-symbol=clash bar.o bar2.o
$ 
Run Code Online (Sandbox Code Playgroud)

现在,您可以成功链接已修改的对象 - 程序的行为应该如下:

$ gcc -o test main.o foo.o bar2.o
$ ./test
foo: Hello
bar: world
$ 
Run Code Online (Sandbox Code Playgroud)

  • 如果碰撞函数仅在单个文件中使用,则根本不需要导出它,因此使其"静态"应该起作用.这将适用于我上面的琐碎例子.(我假设您无法更改原始源,并且需要使用对象,当您说您无法重命名时.)如果您*需要*需要在早期链接阶段为对象之间的引用导出的符号(例如,链接部分对象或库),然后事情会更加困难,并且将其排序将取决于构建过程的更精细细节. (2认同)