libpthread.so.0: błąd podczas dodawania symboli: brak DSO w linii poleceń

205

Podczas kompilowania openvswitch-1.5.0 napotkałem następujący błąd kompilacji:

 gcc -Wstrict-prototypes -Wall -Wno-sign-compare -Wpointer-arith
     -Wdeclaration-after-statement -Wformat-security -Wswitch-enum -Wunused-parameter -Wstrict-aliasing -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -Wno-override-init  -g -O2 -export-dynamic ***-lpthread***  -o utilities/ovs-dpctl utilities/ovs-dpctl.o lib/libopenvswitch.a
 /home/jyyoo/src/dpdk/build/lib/librte_eal.a
 /home/jyyoo/src/dpdk/build/lib/libethdev.a
 /home/jyyoo/src/dpdk/build/lib/librte_cmdline.a
 /home/jyyoo/src/dpdk/build/lib/librte_hash.a
 /home/jyyoo/src/dpdk/build/lib/librte_lpm.a
 /home/jyyoo/src/dpdk/build/lib/librte_mbuf.a
 /home/jyyoo/src/dpdk/build/lib/librte_ring.a
 /home/jyyoo/src/dpdk/build/lib/librte_mempool.a
 /home/jyyoo/src/dpdk/build/lib/librte_malloc.a -lrt -lm 
     /usr/bin/ld: /home/jyyoo/src/dpdk/build/lib/librte_eal.a(eal.o): undefined reference
     to symbol 'pthread_create@@GLIBC_2.2.5'
     /lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from 
     command line

Jeśli spróbuję zobaczyć symbole libpthread, wygląda dobrze.

$ readelf -s /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_create
   199: 0000000000008220  2814 FUNC    GLOBAL DEFAULT   13 pthread_create@@GLIBC_2.2.5
   173: 0000000000008220  2814 FUNC    LOCAL  DEFAULT   13 __pthread_create_2_1
   462: 0000000000008220  2814 FUNC    GLOBAL DEFAULT   13 pthread_create@@GLIBC_2.2

Czy możesz podać jakieś wskazówki lub wskazówki?

jaeyong
źródło
link_libraries (pthread)
Alex Punnen
# readelf -s /lib/x86_64-linux-gnu/libncurses.so readelf: Błąd: Nie można znaleźć „/lib/x86_64-linux-gnu/libncurses.so”. Komunikat o błędzie systemu: Zbyt wiele poziomów dowiązań symbolicznych
Ashish Karpe
Możliwy duplikat DSO brakujący z wiersza poleceń
luator
4
Cholera, zrobiłem gccnieg++
Dodaj Ogłoszenie SELF

Odpowiedzi:

163

Należy wspomnieć biblioteki w wierszu poleceń po pliki wynikowe są kompilowane:

 gcc -Wstrict-prototypes -Wall -Wno-sign-compare -Wpointer-arith -Wdeclaration-after-statement -Wformat-security -Wswitch-enum -Wunused-parameter -Wstrict-aliasing -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -Wno-override-init \
     -g -O2 -export-dynamic -o utilities/ovs-dpctl utilities/ovs-dpctl.o \
     lib/libopenvswitch.a \
     /home/jyyoo/src/dpdk/build/lib/librte_eal.a /home/jyyoo/src/dpdk/build/lib/libethdev.a /home/jyyoo/src/dpdk/build/lib/librte_cmdline.a /home/jyyoo/src/dpdk/build/lib/librte_hash.a /home/jyyoo/src/dpdk/build/lib/librte_lpm.a /home/jyyoo/src/dpdk/build/lib/librte_mbuf.a /home/jyyoo/src/dpdk/build/lib/librte_ring.a /home/jyyoo/src/dpdk/build/lib/librte_mempool.a /home/jyyoo/src/dpdk/build/lib/librte_malloc.a \
     -lrt -lm -lpthread 

Objaśnienie: łączenie zależy od kolejności modułów. Symbole są najpierw wymagane, a następnie łączone z biblioteki, która je ma. Musisz więc określić moduły, które najpierw używają bibliotek, a biblioteki po nich. Lubię to:

gcc x.o y.o z.o -la -lb -lc

Ponadto w przypadku zależności cyklicznej należy kilkakrotnie podać tę samą bibliotekę w wierszu poleceń. Dlatego w przypadku, gdy libbpotrzebny jest symbol z libci libcpotrzebny jest symbol z libb, wierszem poleceń powinno być:

gcc x.o y.o z.o -la -lb -lc -lb
Michael Pankov
źródło
23
Myślę, że możesz zrobić -Wl,--start-group -la -lb- -lc -Wl,--end-groupdla zależności cyklicznych.
Z bozonem
2
Uwaga: dotyczy to również plików źródłowych - powinny być wymienione przed bibliotekami. Możesz pomyśleć o wynikowych plikach obiektowych zajmujących miejsce plików źródłowych w wierszu poleceń i zastosować tę samą kolejność, jak powyżej.
jspencer
Gdzie należy dodać -lpthread przy użyciu make do budowy aplikacji?
codezombie
50

Komunikat o błędzie zależy od wersji dystrybucji / kompilatora:

Ubuntu Saucy:

/usr/bin/ld: /mnt/root/ffmpeg-2.1.1//libavformat/libavformat.a(http.o): undefined reference to symbol 'inflateInit2_'
/lib/x86_64-linux-gnu/libz.so.1: error adding symbols: DSO missing from command line

Ubuntu Raring: (więcej informacji)

/usr/bin/ld: note: 'uncompress' is defined in DSO /lib/x86_64-linux-gnu/libz.so.1 so try adding it to the linker command line

Rozwiązanie: Być może brakuje biblioteki na etapach kompilacji podczas etapu łączenia. W moim przypadku dodałem „-lz” do flag makefile / GCC.

Tło: DSO to dynamiczny obiekt współdzielony lub biblioteka współdzielona.

kevinf
źródło
1
Użyłem tego rozwiązania, budując kolejny projekt, który dawał ten sam błąd, dodając -lz do LDFLAGS i działało idealnie. Dzięki!
Mark Ellul
Nadal dla mnie błąd: / usr / bin / ld: gaSim.o: niezdefiniowane odniesienie do symbolu 'pthread_create @@ GLIBC_2.1' /lib/i386-linux-gnu/libpthread.so.0: błąd podczas dodawania symboli: DSO brak w wierszu poleceń
Aerox
Częściowo rozwiązany dodając „-lpthread”, ale teraz pokazuje mi: gaSim.c :(. Text + 0x11d6): niezdefiniowane odniesienie do „glewInit”
Aerox
@Aerox: bo glewInitpotrzebujesz-lGLEW
mchiasson
19

tło

The DSO missing from command lineWiadomość zostanie wyświetlona, gdy łącznik nie znajdzie wymaganej symbol ze to normalne, ale symbol wyszukiwania jest dostępny w jednym z zależnościami o bezpośrednio określonej biblioteki dynamicznej.

W przeszłości linker uważał za dostępne symbole w zależnościach określonych języków. Ale to zmieniło się w niektórych późniejszych wersjach, a teraz linker wymusza ściślejsze spojrzenie na to, co jest dostępne. Wiadomość ma zatem pomóc w tym przejściu.

Co robić?

Jeśli jesteś opiekunem oprogramowania

Powinieneś rozwiązać ten problem, upewniając się, że wszystkie biblioteki potrzebne do spełnienia potrzebnych symboli są określone bezpośrednio w wierszu poleceń konsolidatora. Pamiętaj też, że kolejność ma często znaczenie.

Jeśli tylko próbujesz skompilować oprogramowanie

Aby obejść ten problem, można powrócić do bardziej liberalnego widoku dostępnych symboli za pomocą opcji -Wl,--copy-dt-needed-entries .

Typowe sposoby wprowadzania tego do kompilacji to eksportowanie LDFLAGS przed uruchomieniem configurelub podobnym:

export LDFLAGS="-Wl,--copy-dt-needed-entries"

Czasami przejście LDFLAGS="-Wl,--copy-dt-needed-entries"bezpośrednio do makemoże również działać.

Skorupa
źródło
Wersja gcc 7.4.0 (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1) nie rozpoznała tej flagi.
UserX
1
To nie jest opcja gcc, więc albo brakuje Ci -Wl,bitu, albo masz linker, który nie obsługuje tych opcji. Jakiego linkera używasz? Ta odpowiedź zakłada klasyczny linker binutils (ld.bfd). Binutils gold linker (ld.gold) dokumentuje --copy-dt-needed-entriesjako „Nieobsługiwany”. Więc jeśli masz ten (lub inny linker, który nie obsługuje tej opcji) jako domyślny, być może będziesz musiał postępować zgodnie z sekcją dla opiekunów lub przejść do klasycznego ld do łączenia. Myślę, że możesz -fuse-ld=ld.bfddo tego użyć .
Skorupa
14

Znalazłem inny przypadek i dlatego myślę, że wszyscy się mylicie.

Oto co miałem:

/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: eggtrayicon.o: undefined reference to symbol 'XFlush'
/usr/lib64/libX11.so.6: error adding symbols: DSO missing from command line

Problem polega na tym, że wiersz poleceń NIE zawierał -lX11- chociaż libX11.so należy dodać jako zależność, ponieważ w argumentach były również biblioteki GTK i GNOME.

Tak więc jedynym wyjaśnieniem dla mnie jest to, że ta wiadomość mogła mieć na celu pomóc , ale nie zrobiła tego poprawnie. Prawdopodobnie było to proste: biblioteka, która zawiera ten symbol, nie została dodana do wiersza poleceń.

Zwróć uwagę na trzy ważne zasady dotyczące łączenia w POSIX:

  • Biblioteki dynamiczne mają zdefiniowane zależności, więc tylko biblioteki z najwyższej zależności powinny być dostarczane w dowolnej kolejności (chociaż po bibliotekach statycznych)
  • Biblioteki statyczne mają właśnie niezdefiniowane symbole - od Ciebie zależy znajomość ich zależności i podanie ich wszystkich w wierszu poleceń
  • W bibliotekach statycznych kolejność jest zawsze następująca: najpierw requester , dostawca podąża . W przeciwnym razie pojawi się niezdefiniowany komunikat z symbolem, tak jak wtedy, gdy zapomnisz dodać bibliotekę do wiersza poleceń
  • Kiedy określisz bibliotekę za pomocą -l<name>, nigdy nie wiesz, czy zajmie lib<name>.solub lib<name>.a. Biblioteka dynamiczna jest preferowana, jeśli zostanie znaleziona, a biblioteki statyczne można wymusić tylko za pomocą opcji kompilatora - to wszystko. I czy masz jakieś problemy jak wyżej, zależy to od tego, czy posiadałeś biblioteki statyczne czy dynamiczne
  • Czasami zależności mogą brakować w bibliotekach dynamicznych: D
Ethouris
źródło
Program ma nie tylko na celu pomóc, ale linker musi rozwiązać te nazwy. Błąd jest całkowicie poprawny. Gdyby kompilator postanowił to przepuścić, dostaniesz po prostu segfault za dostęp do czegoś, czego nie ma w binarnym środowisku uruchomieniowym.
kevr
1
Aby dodać, możliwe jest, że na różnych platformach źródło jest kompilowane inaczej; to, co jest połączone w jednym systemie, nie może być połączone w innym. Zazwyczaj tak nie jest, ale jest w 100% prawdopodobne.
kevr
Problem nie polega na tym, że nie jest prawidłowy, ale że nie jest dokładnie pomocne w znalezieniu przyczyny problemu.
Ethouris,
7

Odkryłem, że mam ten sam błąd. Kompilowałem kod zarówno z lapack, jak i blas. Gdy zmieniłem kolejność wywoływania dwóch bibliotek, błąd zniknął.

„LAPACK_LIB = -llapack -lblas” zadziałało, gdy „LAPACK_LIB = -lblas -llapack” dał błąd opisany powyżej.

użytkownik3112632
źródło
9
Występuje ten błąd w projekcie zdefiniowanym przez cmake ... więc czy w Cmake jest błąd, który źle ustawia kolejność linkerów?
Peter Karasev
odpowiadając na @peterkarasev: spróbuj użyć find_package(Threads)itarget_link_libraries( ... ${CMAKE_THREAD_LIBS_INIT})
activedecay
7

Zetknąłem się również z tym samym problemem. Nie wiem dlaczego, po prostu dodałem -lpthreadopcję do kompilatora i wszystko w porządku.

Stary:

$ g++ -rdynamic -m64 -fPIE -pie  -o /tmp/node/out/Release/mksnapshot ...*.o *.a -ldl -lrt

dostałem następujący błąd. Jeśli dołączę -lpthreadopcję do powyższego polecenia, to OK.

/usr/bin/ld: /tmp/node/out/Release/obj.host/v8_libbase/deps/v8/src/base/platform/condition-variable.o: undefined reference to symbol 'pthread_condattr_setclock@@GLIBC_2.3.3'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
osexp2003
źródło
To zadziałało dla mnie; Musiałem dodać drugi „redundantny” -lpthread do polecenia g ++ w pliku makefile, który wykonuje link. (Pojawił się już raz na liście LIBS w pliku makefile.) Dodałem także „-L / lib / x86_64-linux-gnu” do definicji LDFLAGS w pliku makefile.
UserX
2

Odkryłem, że czasami biblioteka, na którą narzeka linker, nie jest przyczyną problemu. Być może istnieje sprytny sposób, aby dowiedzieć się, gdzie jest problem, ale to właśnie robię:

  • Skomentuj wszystkie połączone biblioteki w poleceniu link.
  • Wyczyść wszystkie .o, .so itp. (Zwykle wystarczy wyczyścić, ale możesz chcieć uruchomić rekurencyjne find + rm lub coś podobnego).
  • Odkomentuj biblioteki w poleceniu link pojedynczo i w razie potrzeby ponownie uporządkuj kolejność.

@peter karasev: Natknąłem się na ten sam problem z projektem cmake gcc 4.8.2 na CentOS7. Ważna jest kolejność bibliotek w sekcji „target_link_libraries”. Wydaje mi się, że cmake po prostu przekazuje listę linkerowi w niezmienionej postaci, tzn. Nie próbuje ustalić prawidłowej kolejności. Jest to uzasadnione - jeśli pomyślisz o tym, cmake nie może wiedzieć, jaka jest poprawna kolejność, dopóki połączenie nie zostanie pomyślnie zakończone.

AhrB
źródło
2

Dodaj: CFLAGS="-lrt"iLDFLAGS="-lrt"

劉 大為
źródło
1

Ten sam problem przydarzył mi się, gdy wykonałem distccprojekt w C ++; W końcu to rozwiązałem export CXX="distcc g++".

Jason Geng
źródło
1

jeśli używasz cmake i używanych pthreads, spróbuj dodać następujące linie

find_package(Threads)
target_link_libraries(${CMAKE_THREAD_LIBS_INIT})
Bowman Han
źródło
0

To samo przydarzyło mi się, gdy instalowałem test porównawczy HPCC (obejmuje HPL i kilka innych testów porównawczych). Dodałem -lmdo flag kompilatora w skrypcie kompilacji, a następnie pomyślnie skompilowałem.

Jon Doh
źródło
3
To nie odpowiada ani na to konkretne pytanie, ani nie daje ogólnej odpowiedzi dla rodziny o podobnych problemach. Jest to wysoce zlokalizowana odpowiedź na zupełnie inne pytanie .
Hermann Döppes,
0

Jeśli używasz g++, upewnij się, że gcczamiast tego nie działasz

Martin R.
źródło
3
Czemu? Czy mógłbyś trochę rozwinąć?
Ivan Ivković
@ IvanIvković dobrze, gcc jest kompilatorem C, g ++ jest kompilatorem C ++. Podczas gdy C ++ może kompilować C, gcc nie może kompilować C ++.
Jean-Marc Zimmer
0

Spróbuj dodać -pthreadna końcu listy bibliotek w Makefile .

To zadziałało dla mnie.

Ricky
źródło
0

Jeśli używasz CMake, istnieje kilka sposobów na jego rozwiązanie:

Rozwiązanie 1: Najbardziej elegancki

add_executable(...)
target_include_directories(...)
target_link_libraries(target_name pthread)

Rozwiązanie 2: Korzystanie z CMakefind_package

find_package(Threads REQUIRED) # this will generate the flag for CMAKE_THREAD_LIBS_INIT

add_executable(...)
target_include_directories(...)
target_link_libraries(target_name ${CMAKE_THREAD_LIBS_INIT})

Rozwiązanie 3: Zmień flagi CMake

# e.g. with C++ 17, change to other version if you need
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -pthread")
biendltb
źródło