Pytanie Jak zbudować udostępnioną bibliotekę (.so) bez zakodowanych pełnych ścieżek zależności?


Muszę zbudować dwie biblioteki współużytkowane 3rd party, więc ich pliki .so będą ponownie wykorzystywane przez inne projekty. Jednak po kompilacji jedna z tych bibliotek zawiera stałą ścieżkę do drugiej. Ta ścieżka jest nieważna na innych komputerach i powoduje ostrzeżenia linkera. Jak mogę zapobiec umieszczeniu pełnej ścieżki w wynikowych plikach .so?

Detale:

Pierwsze źródło biblioteki: ~/dev/A
Drugie źródło biblioteki: ~/dev/B

Obaj mają configure skrypt do generowania plików make. Biblioteka B zależy od A. Więc najpierw buduję A:

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

Potem buduję B:

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

Następnie chcę załadować zawartość ~/dev/A-install i ~/dev/B-install do naszego serwera plików, aby inne zespoły i maszyny budujące mogły używać plików binarnych. Ale otrzymują ostrzeżenia linkera, gdy próbują go użyć B:

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

Kiedy biegnę ldd libB.so to daje:

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

Oczywiście ta ścieżka istnieje tylko na moim komputerze i nie można jej znaleźć na innych komputerach.

Jak mogę usunąć pełną, zakodowaną na stałe ścieżkę z libB.so?

Dzięki.


12
2017-10-27 04:35


pochodzenie


Jak połączyć? Z libtool? W tym wypadku patchelf może pomóc w pozbyciu się zakodowanej ścieżki (RPATH). - Benjamin Bannier
Dlaczego nie używać prefiksu, który nie jest zależny od twojego środowiska, tj ~? Dlaczego nie użyć czegoś takiego jak powiedz /opt jako prefiks, który nie jest zależny od zmiennej środowiskowej, takiej jak $HOME (~)? Możesz spróbować LD_PRELOAD może - another.anon.coward
Idealnie mógłbyś zmienić configure skrypt, aby zapobiec temu problemowi. Jeśli chcesz edytować biblioteki, słyszałem dobre rzeczy o elfsh (eresi-project.org). - Beta
@ another.anon.coward, używam ~ przedrostka tutaj dla jasności. W rzeczywistości jest to pełna ścieżka do jakiegoś katalogu. Ale w każdym razie ten katalog jest unikalny dla mojego komputera i niekoniecznie obecny na innych. - Alex Blekhman
The configure skrypt jest przeznaczony do użycia w tej sytuacji. Tak, nie jest to całkowicie oczywiste z dokumentacji, dopóki nie przeczytasz jej bardzo uważnie. - Jan Hudec


Odpowiedzi:


Musisz użyć --prefix wartość, która będzie ważna w środowisko wykonawcze środowisko dla obu pakietów!

Niż nadpisujesz prefix lub DESTDIR (prefix zastępuje prefiks, DESTDIR jest wstępnie do niego, ale działa bardziej niezawodnie) na linii poleceń make podczas instalacji. Lubić:

~/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

lub (co jest preferowane i jak używają go wszystkie narzędzia do tworzenia pakietów):

~/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

ponieważ w ten sposób instalujesz ~/dev/A-install/$prefix, więc z domyślnym prefiksem ~/dev/A-install/usr/local. Zaletą tej późniejszej opcji jest to, że jeśli przedefiniujesz określone ścieżki instalacji bez odwoływania się do prefiksu (np --sysconfdir=/etc), DESTDIR nadal będzie do niego dołączany, ale nie wpłynie na to prefix.


4
2017-10-27 09:35



Dzięki Jan! DESTDIR jest dokładnie tym, czego potrzebowałem. - Alex Blekhman


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

Ta opcja linkera jest odpowiedzialna za zapisanie ścieżki wewnątrz biblioteki. Musisz jakoś to usunąć.

Zobacz za pomocą ./configure --help jeśli jest jakaś opcja, która może mieć na to wpływ. Inną opcją jest ręczna edycja pliku Makefile i usunięcie tej opcji.

== edit2 == Jeszcze jedna rzecz

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

Jeśli libA.so i libB.so nie mają SONAMEŁączenie ich tak jak "~ / deps / A / lib / libA.so" spowoduje również zapisanie ścieżki. Soname jest ustawiony za pomocą -Wl,-soname,<soname> opcja linkera podczas budowania biblioteki współdzielonej.

Jeśli soname jest ustawione w bibliotece współdzielonej, łączenie jej za pomocą "~/deps/A/lib/libA.so"Formularz jest w porządku.

Tak jak Jan wspomniał w komentarzach, lepszym sposobem jest użycie "-Llibrary/path -llibrary_name" bez rpath.

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

2
2017-10-27 07:19



IIRC to -Lpath -lname ma nie zakodować pełną ścieżkę podczas path/name (Nie -l; nie możesz pisać -lpath/name) robi zakodować to. Więc -L + -l kombinacja musi być używana -Wl,-rpath nie wolno używać, ponieważ dodaje ścieżkę z powrotem po użyciu -l uniknęli tego. - Jan Hudec
W każdym razie jest to libtool, który dodaje ścieżkę rpath i robi to, aby rzeczy działały w bardziej powszechnym przypadku, gdy chcesz zainstalować rzeczy w domu. - Jan Hudec
@ Jan Hudec Nie powiedziałem, że -L / -l są problemem (rpath jest), wspomniałem tylko, że istnieje niepotrzebne powielanie ścieżki biblioteki w kilku parametrach. W każdym razie usunięcie edycji, aby uniknąć nieporozumień. - Dmitry Yudakov


Po uruchomieniu ldd libB.so daje:

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

Rozwiązaniem niskiego poziomu tego problemu jest użycie opcji "-soname = libA.so" po połączeniu biblioteki libA.so. Po zdefiniowaniu SONAME dla obiektu współużytkowanego, linker nie będzie umieszczał bezwzględnych ścieżek podczas łączenia z tym obiektem współdzielonym.

OP używa "configure", więc nie jest to łatwe rozwiązanie, jeśli nie chce wejść do wnętrza pliku Makefile wygenerowanego przez skrypt konfiguracyjny.


1
2018-04-17 20:39





Właśnie mnie przyłapałam na myśleniu, że mam ten sam problem. Żadna z powyższych odpowiedzi nie pomogła mi. Ilekroć próbowałem

ldd libB.so 

Wchodzę na wyjście:

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

więc pomyślałem, że mam wytyczoną na stałe ścieżkę. Okazuje się, że zapomniałem, że ustawiłem LD_LIBRARY_PATH dla testów lokalnych. Czyszczenie LD_LIBRARY_PATH oznaczało, że ldd znalazł poprawną zainstalowaną bibliotekę w / usr / lib /


0
2017-10-25 11:19



Posługiwać się objdump -p libB.so | grep NEEDED zobaczyć, nie ldd. - minghua


Być może używając -rpath i -soname opcje do ld może pomóc (zakładając pakiet binutils lub binutils.gold dla ld w ostatnim systemie Linux)?


-1
2017-10-27 05:12



Czy chcesz używać tych flag z moją aplikacją lub z B biblioteka? - Alex Blekhman
Dokładnie przeciwległy. On musi ZATRZYMAĆ używając -rpath; ścieżka rpath jest przechowywana, ale jest całkowicie błędna. - Jan Hudec
... i -rpath jest dodawany przez libtool z jego obrzydliwości, więc musi powiedzieć libtool, żeby go tam nie umieszczać ... - Jan Hudec