2012-01-04 31 views
8

Tôi đang quan sát sự khác biệt khi cố thực hiện thao tác tương tự trên GCC 4.4 và GCC 4.5. Bởi vì mã tôi đang làm điều này với là độc quyền, tôi không thể cung cấp nó, nhưng tôi đang quan sát một sự thất bại tương tự với trường hợp thử nghiệm đơn giản này.GCC 4.5 so với 4.4 liên kết với các phụ thuộc

Điều cơ bản tôi đang cố gắng làm là có một thư viện được chia sẻ (libb) phụ thuộc vào thư viện được chia sẻ khác (liba). Khi tải libb, tôi giả định rằng liba cũng nên được nạp - mặc dù libb không nhất thiết phải sử dụng các ký hiệu trong liba.

Điều tôi đang quan sát là khi tôi biên dịch với GCC 4.4, tôi quan sát thấy rằng liba được nạp, nhưng nếu tôi biên dịch với GCC 4.5, thì libb không được nạp.

Tôi có một trường hợp thử nghiệm nhỏ bao gồm hai tệp, a.c và b.c. Nội dung của các tập tin:

//a.c 
int a(){ 
    return 0; 
} 

//b.c 
int b(){ 
    return 0; 
} 
//c.c 
#include <stdio.h> 
int a(); 
int b(); 

int main() 
{ 
    printf("%d\n", a()+b()); 
    return 0; 
} 
//test.sh  
$CC -o liba.so a.c -shared 
$CC -o libb.so b.c -shared -L. -la -Wl,-rpath-link . 
$CC c.c -L. -lb -Wl,-rpath-link . 
LD_LIBRARY_PATH=. ./a.out 

Đây là kết quả của tôi với các phiên bản khác nhau của GCC

$ CC=gcc-4.4 ./test.sh 
1 
$ CC=gcc-4.5 ./test.sh 
/tmp/cceJhAqy.o: In function `main': 
c.c:(.text+0xf): undefined reference to `a' 
collect2: ld returned 1 exit status 
./test.sh: line 4: ./a.out: No such file or directory 
$ CC=gcc-4.6 ./test.sh 
/tmp/ccoovR0x.o: In function `main': 
c.c:(.text+0xf): undefined reference to `a' 
collect2: ld returned 1 exit status 
./test.sh: line 4: ./a.out: No such file or directory 
$ 

thể bất cứ ai giải thích những gì đang xảy ra? Thêm một chút thông tin nữa là ldd trên libb.so hiển thị liba.so trên GCC 4.4 nhưng không phải trên GCC 4.5.

EDIT

tôi đã thay đổi test.sh như sau:

$CC -shared -o liba.so a.c 
$CC -L. -Wl,--no-as-needed -Wl,--copy-dt-needed-entries -la -shared -o libb.so b.c -Wl,-rpath-link . 
$CC -L. c.c -lb -Wl,-rpath-link . 
LD_LIBRARY_PATH=. ./a.out 

Điều này đã cho kết quả sau với GCC 4.5:

/usr/bin/ld: /tmp/cc5IJ8Ks.o: undefined reference to symbol 'a' 
/usr/bin/ld: note: 'a' is defined in DSO ./liba.so so try adding it to the linker command line 
./liba.so: could not read symbols: Invalid operation 
collect2: ld returned 1 exit status 
./test.sh: line 4: ./a.out: No such file or directory 
+0

Môi trường xây dựng của tôi là Ubuntu 11.10 x86-64 –

+0

Trên Debian 6.0.3, đóng gói GCC 4.4 xử lý các ví dụ mà không có vấn đề. Gói GCC 4.3 được đóng gói phàn nàn về cờ '-fPIC' bị thiếu. –

Trả lời

11

Dường như có những thay đổi trong cách thư viện DT_NEEDED được xử lý trong khi liên kết theo số ld. Dưới đây là phần có liên quan của hiện tại man ld:

Với --copy-dt-needed-entries thư viện động nêu trên dòng lệnh sẽ đệ quy tìm kiếm, sau thẻ DT_NEEDED của họ để các thư viện khác, để giải quyết những biểu tượng theo yêu cầu của nhị phân đầu ra. Với cài đặt mặc định , việc tìm kiếm các thư viện động theo sau sẽ dừng lại với chính thư viện động. Không có liên kết DT_NEEDED nào được duyệt qua để giải quyết các ký hiệu.

(một phần của phần --copy-dt-needed-entries).

Một số thời gian giữa GCC 4.4 và GCC 4.5 (dường như, xem một số tham chiếu here - không thể tìm thấy bất kỳ điều gì thực sự có thẩm quyền), mặc định được thay đổi từ tìm kiếm đệ quy, không tìm kiếm đệ quy (như bạn đang thấy GCC).

Trong mọi trường hợp, bạn có thể (và nên) sửa chữa nó bằng cách xác định liba ở liên kết cuối cùng bước của bạn:

$CC c.c -L. -lb -la -Wl,-rpath-link . 

Bạn có thể kiểm tra xem thiết lập mối liên kết này thực sự là (ít nhất là một phần của) các vấn đề bằng cách chạy với trình biên dịch mới hơn của bạn và dòng lệnh này:

$CC c.c -L. -Wl,--copy-dt-needed-entries -lb -Wl,--no-copy-dt-needed-entries \ 
     -Wl,-rpath-link . 
+0

Đó sẽ là một lời giải thích rất tốt, nhưng việc thêm cờ không thay đổi kết quả. Tôi đã thử thêm cả hai khi xây dựng libb.so và khi xây dựng cc –

+0

Để tham khảo, phiên bản LD của tôi là GNU ld (GNU Binutils cho Ubuntu) 2.21.53.20110810 –

+0

Cờ chỉ cần trên liên kết cuối cùng, chứ không phải khi xây dựng các tệp '.so'. Trong mọi trường hợp, bản sửa lỗi thực sự là liên kết tệp thực thi của bạn với cả 'libb' ** và **' liba'. (Tôi trên ld 2.22.) – Mat

Các vấn đề liên quan