2011-10-27 29 views
12

Tôi cần phải xây dựng hai thư viện chia sẻ của bên thứ ba, vì vậy các tệp .so của chúng sẽ được các dự án khác sử dụng lại. Tuy nhiên, sau khi xây dựng một trong các thư viện này có chứa đường dẫn mã hóa cứng khác. Đường dẫn này không hợp lệ trên các máy khác và gây cảnh báo liên kết. Làm thế nào tôi có thể ngăn chặn đường dẫn đầy đủ từ được nhúng trong các tập tin .so kết quả?Làm thế nào để xây dựng một thư viện được chia sẻ (.so) mà không có đường dẫn phụ thuộc đầy đủ được mã hóa cứng?

chi tiết:

Đầu thư viện nguồn: ~/dev/A
nguồn thư viện thứ hai: ~/dev/B

Cả hai đều có configure kịch bản để tạo ra làm cho tập tin. Thư viện B tùy thuộc vào A. Vì vậy, lần đầu tiên tôi xây dựng A:

$ ~/dev/A/configure --prefix=~/dev/A-install 
$ make && make install 

Sau đó, tôi xây dựng B:

$ ~/dev/B/configure --prefix=~/dev/B-install --with-A=~/dev/A-install 
$ make && make install 

Sau đó, tôi muốn tải lên nội dung của ~/dev/A-install~/dev/B-install đến máy chủ tập tin của chúng tôi, vì vậy các đội khác và xây dựng máy có thể sử dụng các tệp nhị phân. Nhưng họ nhận được lời cảnh báo mối liên kết khi họ cố gắng sử dụng B:

/usr/bin/ld: warning: libA.so.2, needed by /.../deps/B/lib/libB.so, not found (try using -rpath or -rpath-link) 

Khi tôi chạy ldd libB.so nó mang lại:

... 
libA.so.2 => /home/alex/dev/A-install/lib/libA.so.2 

Rõ ràng con đường này chỉ tồn tại trên máy tính của mình và không thể được tìm thấy trên các máy khác.

Tôi làm cách nào để xóa đường dẫn được mã hóa đầy đủ khỏi libB.so?

Cảm ơn.

+0

Làm cách nào để bạn liên kết? Với libtool? Trong trường hợp đó 'patchelf' có thể giúp bạn loại bỏ đường dẫn được mã hóa (RPATH). –

+0

Tại sao không sử dụng tiền tố không phụ thuộc vào môi trường của bạn, tức là '~'? Tại sao không sử dụng một cái gì đó như nói '/ opt' là tiền tố mà không phụ thuộc vào biến môi trường như' $ HOME' ('~')? Bạn có thể thử ['LD_PRELOAD'] (http://stackoverflow.com/questions/426230/what-is-the-ld-preload-trick) có lẽ –

+0

Lý tưởng nhất là bạn có thể thay đổi tập lệnh' configure' để ngăn chặn vấn đề này. Nếu bạn muốn chỉnh sửa các thư viện, tôi đã nghe những điều tốt đẹp về elfsh (http://www.eresi-project.org). – Beta

Trả lời

4

Bạn phải sử dụng --prefix giá trị mà sẽ có hiệu lực trong thời gian chạy môi trường cho cả gói!

Hơn bạn ghi đè prefix hoặc DESTDIR (prefix thay thế tiền tố, DESTDIR được thêm vào trước, nhưng hoạt động đáng tin cậy hơn) khi tạo dòng lệnh khi cài đặt. Giống như:

~/dev/A$ ./configure 
~/dev/A$ make 
~/dev/A$ make install prefix=~/dev/A-install 
~/dev/B$ ./configure --with-A=~/dev/A-install 
~/dev/B$ make 
~/dev/B$ make install prefix=~/dev/B-install 

hoặc (được ưa thích và là cách tất cả các công cụ gói xây dựng sử dụng nó):

~/dev/A$ ./configure 
~/dev/A$ make 
~/dev/A$ make install DESTDIR=~/dev/A-install 
~/dev/B$ ./configure --with-A=~/dev/A-install/usr/local 
~/dev/B$ make 
~/dev/B$ make install prefix=~/dev/B-install 

vì cách này bạn đang cài đặt để ~/dev/A-install/$prefix, vì vậy với mặc định tiền tố ~/dev/A-install/usr/local. Ưu điểm của tùy chọn sau này là, nếu bạn xác định lại một số đường dẫn cài đặt cụ thể mà không tham chiếu đến tiền tố (nói --sysconfdir=/etc), DESTDIR sẽ vẫn được thêm vào trước, trong khi nó sẽ không bị ảnh hưởng bởi prefix.

+0

Cảm ơn Jan! 'DESTDIR' chính xác là những gì tôi cần. –

-1

Có lẽ bằng cách sử dụng tùy chọn -rpath-soname để ld có thể giúp (giả sử một binutils hoặc gói binutils.gold cho ld trên một hệ thống Linux gần đây)?

+0

Bạn có ý định sử dụng các cờ này với ứng dụng của tôi hoặc với thư viện 'B' không? –

+0

Vâng, chính xác oposite. Anh ấy cần * STOP * bằng cách sử dụng -rpath; rpath đang được lưu trữ, nhưng hoàn toàn sai. –

+0

... và -rpath đang được thêm vào bởi libtool từ nó ablaination .la, do đó, anh ta cần phải nói với libtool không để đặt nó ở nơi đầu tiên ... –

2
-Wl,-rpath,~/deps/A/lib:~/deps/B/lib:~/dev/MyApp/bin 

Tùy chọn trình liên kết này có trách nhiệm lưu đường dẫn bên trong thư viện. Bạn cần bằng cách nào đó để loại bỏ điều này.

Xem với ./configure --help nếu có một số tùy chọn có thể ảnh hưởng đến điều này. Một tùy chọn khác là chỉnh sửa thủ công makefile và xóa tùy chọn này.

== edit2 == Một điều nữa

-L~/deps/A/lib -L~/deps/B/lib ~/deps/A/lib/libA.so ~/deps/B/lib/libB.so 

Nếu libA.so và libB.so không có SONAME, liên kết chúng như "~/DEPS/A/lib/libA.so" cũng sẽ tiết kiệm đường dẫn. Soname được đặt bằng cách sử dụng tùy chọn liên kết -Wl,-soname,<soname> khi xây dựng thư viện được chia sẻ.

Nếu soname được đặt trong thư viện được chia sẻ, liên kết nó bằng cách sử dụng "~/deps/A/lib/libA.so" biểu mẫu là ok.

Giống như Jan đã đề cập trong nhận xét, cách tốt hơn là sử dụng "-Llibrary/path -llibrary_name" không có rpath.

-L~/deps/A/lib -L~/deps/B/lib -lA -lB 
+0

IIRC -Lpath -lname không * không * mã hóa đầy đủ đường dẫn trong khi 'path/name' (không có' -l'; bạn không thể viết '-lpath/name') * * mã hóa nó. Vì vậy, sự kết hợp '-L' +' -l' phải được sử dụng '-Wl, -rpath' không được sử dụng, vì nó thêm đường dẫn trở lại sau khi sử dụng' -l' tránh nó. –

+0

Dù sao, đó là libtool cho biết thêm rpath và nó làm như vậy để mọi thứ hoạt động trong trường hợp phổ biến hơn nơi bạn muốn cài đặt mọi thứ trong nhà của bạn. –

+0

@Jan Hudec Tôi đã không nói rằng -L/-l là vấn đề (rpath là), vừa đề cập rằng có một số trùng lặp không cần thiết của đường dẫn thư viện trong một số tham số. Dù sao, hãy xóa bản chỉnh sửa để tránh nhầm lẫn. –

0

Tôi vừa mới bắt gặp suy nghĩ rằng tôi có cùng một vấn đề. Không có câu trả lời nào ở trên giúp ích cho tôi. Bất cứ khi nào tôi đã cố gắng

ldd libB.so 

tôi sẽ nhận được trong đầu ra:

libA.so.1 => /home/me/localpath/lib/libA.so.1.0 

và vì vậy tôi nghĩ rằng tôi đã có một con đường cứng. Hóa ra là tôi đã quên tôi đã đặt LD_LIBRARY_PATH cho thử nghiệm cục bộ. Thanh toán bù trừ LD_LIBRARY_PATH nghĩa là ldd tìm thấy thư viện được cài đặt đúng trong/usr/lib/

+1

Sử dụng 'objdump -p libB.so | grep CẦN để xem, không phải 'ldd'. – minghua

1

Khi tôi chạy ldd libB.so nó mang lại:

libA.so.2 =>/home/alex/dev/A-install/lib/libA.so.2

Giải pháp cấp thấp cho vấn đề này là sử dụng tùy chọn "-soname = libA.so" khi bạn liên kết thư viện libA.so. Bằng cách có SONAME được định nghĩa cho một đối tượng được chia sẻ, trình liên kết sẽ không nhúng đường dẫn tuyệt đối khi liên kết với đối tượng được chia sẻ đó.

OP đang sử dụng "định cấu hình", vì vậy đây không phải là giải pháp dễ thực hiện trừ khi anh sẵn sàng đi vào ruột của Makefile được tạo bởi tập lệnh cấu hình.

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