2010-07-14 34 views
5

我使用的是具有gcc 2.95.3的舊系統,我必須鏈接兩個對象,儘管它們之間沒有任何關係,但它們每個都有類似命名的方法。我不能重命名其中的任何一個,但我希望有一種方法可以構建它們,以免連接器發生抱怨。它所抱怨的方法都是由對象內部的類在內部調用的。我能做什麼?如何解決與gcc鏈接的「多個已定義符號」

回答

9

如果你有一個完整的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 
$ 
+1

如何在指定本地對象之前指定對象?在代碼理想情況下,也可能作爲對象編譯的一部分? – CptanPanic 2010-07-19 14:55:09

+2

如果碰撞函數僅用於單個文件中,則根本不需要導出它,因此使其成爲「靜態」應該可以工作。這將與我上面的小例子一起工作。 (我認爲你不能改變原始源代碼,而需要使用對象來處理,而當你說你不能重命名的時候)。如果你需要在早期的鏈接階段爲對象之間的引用導出這些符號(例如,鏈接部分對象或庫),那麼事情就會變得更加困難,並且將其排序取決於構建過程的更精細的細節。 – 2010-07-19 20:02:32