2014-12-09 18 views
6

Tôi muốn sử dụng gcc 4.8.1 cho ứng dụng của tôi (yêu cầu libstdC++. So.6.0.18), tuy nhiên khách hàng chỉ có libstdC++. So.6.0.13. Tôi đã sử dụng -static-libgcc -static-stdlibc++ một lúc, nhưng ứng dụng của tôi bao gồm một số thư viện được liên kết động và một ứng dụng chính. Điều này có nghĩa là khi biên dịch từng thư viện động, chúng phải biên dịch tĩnh một thư viện chuẩn, vốn thừa và lãng phí. Tôi chỉ muốn gửi thư viện chuẩn của sự lựa chọn của tôi với sản phẩm của mình, tuy nhiên mỗi khi tôi chạy ứng dụng của mình trong môi trường như của họ, nó luôn tải thư viện chuẩn sai. Nó thích các phiên bản /usr/lib64/ không có vấn đề gì tôi dường như làm (nó có vẻ được ưu tiên hơn LD_LIBRARY_PATH).Vận chuyển libstdC++, so.6 với ứng dụng

ràng buộc:

  1. tôi không được phép để buộc họ phải nâng cấp lên một thư viện tiêu chuẩn mới.

  2. Tôi không muốn đặt thư viện động tĩnh. (Tôi có thể biên dịch tĩnh mọi thứ vào ứng dụng chính một lần, nhưng có một số rào cản hậu cần ngăn cản tôi biên dịch lại một số thư viện thành các thư viện tĩnh).

-Wl,-rpath=$(path_to_directory) có một chút nguy hiểm, tuy nhiên, điều này là hợp pháp vì khách hàng thực hiện một số cài đặt cho phép tôi đặt biến đường dẫn. Tuy nhiên, thiết lập rpath của stdlibC++ mới của tôi dường như không ghi đè phiên bản /usr/lib64 mặc định. Tôi vẫn gặp phải lỗi GLIBCXX vì nó sẽ không sử dụng đúng thư viện.

Chắc chắn có giải pháp thanh lịch cho điều này?

Có lẽ chỉ có lỗi trong quy trình của tôi. Dưới đây là một ví dụ (xin lỗi về sự kiểm duyệt, nhưng nó chỉ là thứ username):

~/example$ pwd 
/home/username/example 
~/example$ echo $LD_LIBRARY_PATH 

~/example$ ls 
Makefile libstdc++.so.6.0.18 test.cpp 
~/example$ make 
g++ -std=c++11 -Wall -Werror test.cpp -o test 
~/example$ ldd test 
./test: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./test) 
    linux-vdso.so.1 => (0x00007fffe5919000) 
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x000000390b800000) 
    libm.so.6 => /lib64/libm.so.6 (0x0000003904800000) 
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000390b400000) 
    libc.so.6 => /lib64/libc.so.6 (0x0000003904400000) 
    /lib64/ld-linux-x86-64.so.2 (0x0000003904000000) 
~/example$ setenv LD_LIBRARY_PATH /home/username/example 
~/example$ echo $LD_LIBRARY_PATH 
/home/username/example 
~/example$ ldd test 
./test: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./test) 
    linux-vdso.so.1 => (0x00007fff2d3ff000) 
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x000000390b800000) 
    libm.so.6 => /lib64/libm.so.6 (0x0000003904800000) 
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000390b400000) 
    libc.so.6 => /lib64/libc.so.6 (0x0000003904400000) 
    /lib64/ld-linux-x86-64.so.2 (0x0000003904000000) 

kẻ Xin lỗi, tôi đã phạm sai lầm khá ngớ ngẩn ...

~/example$ file libstdc++.so.6.0.18 
libstdc++.so.6.0.18: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped 

Một số dweeb xây dựng phiên bản sai của thư viện, và một dweeb (cụ thể là bản thân mình) đã thử sử dụng nó trên một máy tính 64-bit. Sử dụng LD_LIBRARY_PATH đang hoạt động cùng một lúc ...

+0

Tôi đã mong đợi LD_LIBRARY_PATH hoạt động: Bạn đã thử 'ldd'ing nhị phân của bạn cả khi có và không có LD_LIBRARY_PATH được đặt? Cũng nên nhớ rằng LD_LIBRARY_PATH sẽ không bao giờ tồn tại thông qua độ cao. –

+0

Hiển thị cách bạn đang thiết lập LD_LIBRARY_PATH, và cũng là đầu ra của 'ldd $ x | fgrep ++ 'trong đó' $ x' phạm vi trên tất cả các tệp nhị phân bạn gửi, với tập hợp LD_LIBRARY_PATH và/hoặc '-Wl, -rpath =' có hiệu lực. –

+0

Ok vậy, 'LD_LIBRARY_PATH' được cho là được ưu tiên? Ứng dụng của tôi chạy ở chế độ người dùng, do đó không có người dùng nâng cao. Dưới đây là những gì tôi đã làm: Biên dịch với gcc 4.8.1 (cấu hình của nó giải quyết các liên kết với đúng thư viện), thiết lập 'setenv LD_LIBRARY_PATH/home/myusername /: $ {LD_LIBRARY_PATH}', và sau đó thử chạy/'ldd' chương trình . Các stdlib tôi muốn trong ví dụ này là trong thư mục nhà của tôi. Điều này được cho là được ưu tiên hơn các đường dẫn hệ thống? – Suedocode

Trả lời

4

Vấn đề của bạn là tệp thi hành được liên kết với tên sonname libstdc++.so.6 không phải với tên tệp thư viện đầy đủ libstdc++.so.6.0.16. Trình liên kết động sẽ tìm kiếm libstdc++.so.6 ở các vị trí thông thường (ví dụ: LD_LIBRARY_PATH, DT_RPATH, ldconfig dirs, v.v.) để đảm bảo phiên bản 6.0.18 được tìm thấy, bạn cần một liên kết tượng trưng được gọi là libstdc++.so.6 trỏ đến nó.

Thay vì sử dụng LD_LIBRARY_PATH (đó là mong manh trên máy bạn không kiểm soát, bởi vì người dùng có thể thay đổi môi trường của họ) tôi thích liên kết với '-Wl,-rpath,$ORIGIN' (NB có dấu ngoặc kép là cần thiết để ngăn chặn sự mở rộng vỏ $ORIGIN)

Một RPATH của $ORIGIN yêu cầu trình liên kết động bắt đầu tìm kiếm các thư viện được chia sẻ trong cùng thư mục với tệp thực thi, vì vậy nếu bạn gửi libstdC++, do đó, bên cạnh tệp thực thi của bạn, nó sẽ được tìm thấy. Nếu bạn muốn gửi tệp thi hành trong thư mục bin và có thư viện trong thư mục lib, bạn có thể sử dụng '-Wl,-rpath,$ORIGIN/../lib' hoặc các đường dẫn khác có liên quan đến vị trí của tệp thực thi.

+0

Ahh Tôi đã nhìn thấy điều ORIGIN trước đó, nhưng tôi đã không nhận ra đó là một từ khóa cho mối liên kết; Tôi nghĩ rằng nó chỉ là một biến shell thường được sử dụng (mà sẽ hoàn toàn phản tác dụng). – Suedocode

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