libpthread.so.0: simbol menambahkan kesalahan: DSO hilang dari baris perintah


205

Ketika saya mengkompilasi openvswitch-1.5.0, saya telah menemukan kesalahan kompilasi berikut:

 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

Jika saya mencoba melihat simbol-simbol libpthread, itu terlihat baik-baik saja.

$ 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

Bisakah Anda memberikan petunjuk atau petunjuk?



link_libraries (pthread)
Alex Punnen

# readelf -s /lib/x86_64-linux-gnu/libncurses.so readelf: Kesalahan: Tidak dapat menemukan '/lib/x86_64-linux-gnu/libncurses.so'. Pesan kesalahan sistem: Terlalu banyak level tautan simbolik
Ashish Karpe

Kemungkinan duplikat dari DSO hilang dari baris perintah
luator

4
Sialan, aku gcctidakg++
Post Self

Jawaban:


164

Anda harus menyebutkan pustaka pada baris perintah setelah file objek dikompilasi:

 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 

Penjelasan: tautannya tergantung pada urutan modul. Simbol pertama kali diminta, dan kemudian ditautkan dari perpustakaan yang memilikinya. Jadi, Anda harus menentukan modul yang menggunakan perpustakaan terlebih dahulu, dan perpustakaan setelahnya. Seperti ini:

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

Selain itu, jika ada ketergantungan melingkar, Anda harus menentukan pustaka yang sama pada baris perintah beberapa kali. Jadi jika libbperlu simbol dari libcdan libcmembutuhkan simbol dari libb, baris perintah harus:

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

24
Saya pikir Anda dapat melakukannya -Wl,--start-group -la -lb- -lc -Wl,--end-groupuntuk dependensi melingkar.
Z boson

2
Catatan ini juga berlaku untuk file sumber - mereka harus didaftar sebelum perpustakaan. Anda dapat memikirkan file objek yang dihasilkan menggantikan file sumber di baris perintah, dan menerapkan urutan yang sama seperti di atas.
jspencer

Di mana kita harus menambahkan -lpthread saat menggunakan make untuk membangun aplikasi?
codezombie

50

Pesan kesalahan tergantung pada versi distribusi / kompiler:

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: (lebih informatif)

/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

Solusi: Anda mungkin kehilangan perpustakaan dalam langkah kompilasi Anda, selama tahap penautan. Dalam kasus saya, saya menambahkan '-lz' ke ​​flag makefile / GCC.

Latar Belakang: DSO adalah objek bersama dinamis atau perpustakaan bersama.


1
Saya menggunakan solusi ini membangun proyek lain yang memberikan kesalahan yang sama dengan menambahkan -lz ke LDFLAGS dan itu bekerja dengan sempurna. Terima kasih!
Mark Ellul

Kesalahan masih ada pada saya: / usr / bin / ld: gaSim.o: referensi tidak terdefinisi ke simbol 'pthread_create @@ GLIBC_2.1' /lib/i386-linux-gnu/libpthread.so.0: kesalahan menambahkan simbol: DSO hilang dari baris perintah
Aerox

Sebagian diselesaikan dengan menambahkan '-lpthread', tetapi sekarang ia menunjukkan kepada saya: gaSim.c :(. Teks + 0x11d6): referensi yang tidak ditentukan untuk `glewInit '
Aerox

@ Aerox: untuk glewInit, Anda perlu-lGLEW
mchiasson

19

Latar Belakang

Itu DSO missing from command line pesan akan ditampilkan ketika linker tidak menemukan simbol yang diperlukan dengan itu pencarian normal tapi simbol tersedia di salah satu dependensi dari sebuah perpustakaan yang dinamis langsung ditentukan.

Di masa lalu linker dianggap simbol dalam dependensi dari bahasa yang ditentukan tersedia. Tetapi itu berubah dalam beberapa versi kemudian dan sekarang tautan membuat pandangan yang lebih ketat tentang apa yang tersedia. Dengan demikian pesan ini dimaksudkan untuk membantu transisi itu.

Apa yang harus dilakukan?

Jika Anda adalah pengelola perangkat lunak

Anda harus menyelesaikan masalah ini dengan memastikan bahwa semua perpustakaan yang diperlukan untuk memenuhi simbol yang diperlukan secara langsung ditentukan pada baris perintah linker. Juga perlu diingat bahwa ketertiban sering kali penting.

Jika Anda hanya mencoba untuk mengkompilasi perangkat lunak

Sebagai solusinya, dimungkinkan untuk beralih kembali ke tampilan yang lebih permisif tentang simbol apa yang tersedia dengan menggunakan opsi -Wl,--copy-dt-needed-entries .

Cara umum untuk menyuntikkan ini ke build adalah dengan mengekspor LDFLAGS sebelum berjalan configureatau serupa seperti ini:

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

Terkadang lewat LDFLAGS="-Wl,--copy-dt-needed-entries"langsung ke makemungkin juga berhasil.


gcc versi 7.4.0 (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1) tidak mengenali flag ini.
UserX

1
Ini bukan opsi gcc, jadi Anda kehilangan -Wl,bitnya, atau Anda memiliki tautan yang tidak mendukung opsi ini. Tautan apa yang Anda gunakan? Jawaban ini mengasumsikan tautan binutils klasik (ld.bfd). Tautan emas binutils (ld.gold) mendokumentasikan --copy-dt-needed-entriessebagai "Tidak didukung". Jadi, jika Anda memiliki itu (atau tautan lain yang tidak mendukung opsi ini) sebagai default, Anda mungkin perlu mengikuti bagian untuk pengelola atau beralih ke ld klasik untuk menghubungkan. Saya pikir Anda dapat menggunakannya -fuse-ld=ld.bfduntuk itu.
textshell

14

Saya menemukan kasus lain dan karena itu saya anggap Anda semua salah.

Inilah yang saya miliki:

/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

Masalahnya adalah bahwa baris perintah TIDAK mengandung -lX11 - meskipun libX11.so harus ditambahkan sebagai dependensi karena ada juga pustaka GTK dan GNOME dalam argumen.

Jadi, satu-satunya penjelasan bagi saya adalah bahwa pesan ini mungkin dimaksudkan untuk membantu Anda , tetapi tidak melakukannya dengan benar. Ini mungkin sederhana: perpustakaan yang menyediakan simbol tidak ditambahkan ke baris perintah.

Harap perhatikan tiga aturan penting terkait tautan di POSIX:

  • Perpustakaan dinamis memiliki dependensi yang ditentukan, jadi hanya perpustakaan dari dependensi atas yang harus disediakan dalam urutan apa pun (meskipun setelah perpustakaan statis)
  • Pustaka statis hanya memiliki simbol yang tidak terdefinisi - terserah Anda untuk mengetahui ketergantungannya dan memasok semuanya pada baris perintah
  • Urutan di perpustakaan statis selalu: pemohon terlebih dahulu , penyedia mengikuti . Kalau tidak, Anda akan mendapatkan pesan simbol yang tidak terdefinisi, seperti ketika Anda lupa menambahkan pustaka ke baris perintah
  • Ketika Anda menentukan perpustakaan dengan -l<name>, Anda tidak pernah tahu apakah akan mengambil lib<name>.soatau lib<name>.a. Perpustakaan dinamis lebih disukai, jika ditemukan, dan perpustakaan statis hanya dapat ditegakkan dengan opsi kompiler - itu saja. Dan apakah Anda memiliki masalah seperti di atas, itu tergantung pada apakah Anda memiliki perpustakaan statis atau dinamis
  • Yah, kadang-kadang dependensi mungkin kurang di perpustakaan dinamis: D

Itu tidak hanya dimaksudkan untuk membantu Anda, itu diperlukan oleh penghubung untuk menyelesaikan nama-nama yang dimaksud. Kesalahan ini sepenuhnya valid. Jika kompiler memutuskan untuk membiarkannya, Anda hanya akan mendapatkan segfault untuk mengakses sesuatu yang tidak ada dalam runtime biner.
kevr

1
Untuk menambahkan, ada kemungkinan bahwa pada platform yang berbeda, sumbernya dikompilasi secara berbeda; apa yang ditautkan pada satu sistem mungkin tidak terhubung dengan yang lain. Ini biasanya tidak demikian, tetapi 100% masuk akal.
kevr

Masalahnya bukan itu tidak valid, tetapi itu tidak benar-benar membantu untuk menemukan penyebab masalahnya.
Ethouris

7

Saya menemukan kesalahan yang sama. Saya mengkompilasi kode dengan lapack dan blas. Ketika saya mengganti urutan kedua pustaka yang disebut kesalahan itu hilang.

"LAPACK_LIB = -llapack -lblas" bekerja di mana "LAPACK_LIB = -lblas -llapack" memberikan kesalahan yang dijelaskan di atas.


9
Saya mendapatkan kesalahan ini dalam proyek yang ditentukan cmake ... jadi apakah ada bug di Cmake yang membuat urutan linker salah?
peter karasev

Membalas @peterkarasev: coba gunakan find_package(Threads)dantarget_link_libraries( ... ${CMAKE_THREAD_LIBS_INIT})
activedecay

7

Saya juga mengalami masalah yang sama. Saya tidak tahu mengapa, saya hanya menambahkan -lpthreadopsi ke kompiler dan semuanya baik-baik saja.

Tua:

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

mendapat kesalahan berikut. Jika saya menambahkan -lpthreadopsi ke perintah di atas maka 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

Ini bekerja untuk saya; Saya harus menambahkan yang kedua, "redundant" -lpthread ke perintah g ++ di makefile yang melakukan tautan. (Sudah muncul sekali dalam daftar LIBS di makefile.) Saya juga menambahkan "-L / lib / x86_64-linux-gnu" ke definisi LDFLAGS di makefile.
UserX

2

Apa yang saya temukan adalah bahwa kadang-kadang perpustakaan yang dikeluhkan linker bukan yang menyebabkan masalah. Mungkin ada cara cerdas untuk mencari tahu di mana masalahnya tapi ini yang saya lakukan:

  • Komentari semua perpustakaan yang ditautkan dalam perintah tautan.
  • Bersihkan semua .o, .so, dll. (Biasanya membuat bersih sudah cukup, tetapi Anda mungkin ingin menjalankan pencarian + rm rekursif, atau yang serupa).
  • Batalkan komentar perpustakaan di perintah tautan satu per satu dan atur ulang pesanan sesuai kebutuhan.

@ Peter Karasev: Saya telah menemukan masalah yang sama dengan proyek gake 4.8.2 cmake pada CentOS7. Urutan perpustakaan di bagian "target_link_libraries" penting. Saya kira cmake hanya meneruskan daftar ke linker apa adanya, yaitu tidak mencoba dan mengerjakan urutan yang benar. Ini masuk akal - ketika Anda memikirkannya, cmake tidak bisa tahu apa urutan yang benar sampai tautan berhasil diselesaikan.



1

Masalah yang sama terjadi pada saya ketika saya gunakan distccuntuk membuat proyek c ++ saya; Akhirnya saya menyelesaikannya dengan export CXX="distcc g++".


1

jika Anda menggunakan cmake dan pthreads bekas, coba tambahkan baris berikut

find_package(Threads)
target_link_libraries(${CMAKE_THREAD_LIBS_INIT})

0

Hal yang sama terjadi pada saya ketika saya menginstal benchmark HPCC (termasuk HPL dan beberapa tolok ukur lainnya). Saya menambahkan -lmbendera compiler di skrip build saya dan kemudian berhasil dikompilasi.


3
Ini tidak menjawab pertanyaan khusus ini atau memberikan jawaban umum untuk keluarga yang memiliki masalah serupa. Ini adalah jawaban yang sangat terlokalisasi untuk pertanyaan lain sepenuhnya .
Hermann Döppes

0

Jika menggunakan g++, pastikan bahwa Anda tidak menjalankan gccbukannya


3
Mengapa? Bisakah Anda menguraikan sedikit?
Ivan Ivkovic

@ IvanIvković yah, gcc adalah kompiler C, g ++ adalah kompiler C ++. Sementara C ++ dapat mengkompilasi C, gcc tidak dapat mengkompilasi C ++.
Jean-Marc Zimmer

0

Coba tambahkan -pthreaddi akhir daftar perpustakaan di Makefile .

Ini berhasil untuk saya.


0

Jika Anda menggunakan CMake, ada beberapa cara yang bisa Anda selesaikan:

Solusi 1: Yang paling elegan

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

Solusi 2: menggunakan 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})

Solusi 3: Ubah flag 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")
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.