libpthread.so.0: помилка додавання символів: DSO відсутній у командному рядку


205

Коли я компілюю openvswitch-1.5.0, я зіткнувся з такою помилкою компіляції:

 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

Якщо я спробую побачити символи Росії libpthread, це виглядає чудово.

$ 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

Чи можете ви дати підказки чи покажчики?



link_libraries (pthread)
Алекс Пуннен

# readelf -s /lib/x86_64-linux-gnu/libncurses.so readelf: Помилка: не вдалося знайти '/lib/x86_64-linux-gnu/libncurses.so'. Повідомлення про системну помилку: Занадто багато рівнів символічних посилань
Ashish Karpe


4
Прокляття, я цього gccне зробивg++
Повідомляю себе

Відповіді:


163

Ви повинні згадати бібліотеку в командному рядку після компіляції об'єктних файлів:

 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 

Пояснення: посилання залежить від порядку модулів. Символи спочатку запитуються, а потім пов'язуються з бібліотеки, яка їх містить. Отже, вам потрібно вказати модулі, які спочатку використовують бібліотеки, а після них - бібліотеки. Подобається це:

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

Більше того, якщо існує кругова залежність, вам слід вказати одну і ту ж бібліотеку в командному рядку кілька разів. Тож у випадку, якщо libbпотрібен символ з libcі libcпотрібен символ з libb, командний рядок повинен бути:

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

23
Я думаю, що ти можеш зробити -Wl,--start-group -la -lb- -lc -Wl,--end-groupдля кругової залежності.
Z boson

2
Зверніть увагу, це стосується і вихідних файлів - вони повинні бути перелічені перед бібліотеками. Ви можете придумати отримані об’єктні файли, що займають місце вихідних файлів у командному рядку, і застосувати той самий порядок, як вище.
jspencer

Де слід додати -lpthread при використанні make для створення програми?
codezombie

50

Повідомлення про помилку залежить від версії розповсюдження / компілятора:

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: (більш інформативно)

/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

Рішення: Можливо, вам не вистачає бібліотеки під час етапів компіляції під час етапу зв’язку. У моєму випадку я додав '-lz' для makefile / GCC прапорів.

Передумови: DSO - це динамічний спільний об'єкт або спільна бібліотека.


1
Я використовував це рішення, будуючи інший проект, який давав ту саму помилку, додавши -lz до LDFLAGS, і він працював ідеально. Дякую!
Марк Еллюл

Помилка все ще залишається для мене: / usr / bin / ld: gaSim.o: невизначена посилання на символ 'pthread_create @@ GLIBC_2.1' /lib/i386-linux-gnu/libpthread.so.0: помилка додавання символів: DSO відсутній у командному рядку
Aerox

Частково вирішено додавання '-lpthread', але тепер він показує мені: gaSim.c :(. Текст + 0x11d6): невизначене посилання на `glewInit '
Aerox

@Aerox: бо glewInit, вам потрібно-lGLEW
mchiasson

19

Фон

DSO missing from command lineПовідомлення буде відображатися , коли линкер не знаходить потрібний символ з його звичайним пошуком , але символ доступний в одному з залежностей безпосередньо зазначеної динамічної бібліотеки.

У минулому лінкер вважав доступними символи в залежності від зазначених мов. Але це змінилося в більш пізній версії, і тепер лінкер застосовує більш суворий погляд на те, що є в наявності. Повідомлення, таким чином, покликане допомогти з цим переходом.

Що робити?

Якщо ви підтримуєте програмне забезпечення

Ви повинні вирішити цю проблему, переконавшись, що всі бібліотеки, необхідні для задоволення необхідних символів, безпосередньо вказані в командному рядку лінкера. Також пам’ятайте, що замовлення часто має значення.

Якщо ви просто намагаєтеся скласти програмне забезпечення

Як вирішення, можна повернутись до більш дозволеного уявлення про те, які символи доступні за допомогою параметра -Wl,--copy-dt-needed-entries.

Загальні способи ввести це в збірку - експортувати LDFLAGS перед запуском configureчи подібним чином:

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

Іноді перехід LDFLAGS="-Wl,--copy-dt-needed-entries"безпосередньо до makeможе також спрацювати.


gcc версія 7.4.0 (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1) не визнала цей прапор.
UserX

1
Це не gcc-варіант, тому або ви не вистачаєте в -Wl,біті, або у вас є посилання, яка не підтримує ці параметри. Який линк ви використовуєте? Ця відповідь передбачає класичний бінкер-лінкер (ld.bfd). Документи із золотого бінкеля (ld.gold) у документах --copy-dt-needed-entriesяк "Не підтримується". Тож якщо у вас є цей (або будь-який інший посилання, який не підтримує цю опцію) як за замовчуванням, вам може знадобитися дотримуватися розділу щодо технічного обслуговування або перейти до класичного ld для посилання. Я думаю, ви можете використовувати -fuse-ld=ld.bfdдля цього.
texthell

14

Я знайшов інший випадок, і тому я думаю, ви все помиляєтесь.

Ось що я мав:

/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

Проблема полягає в тому, що командний рядок DID НЕ містить -lX11- хоча libX11.so слід додати як залежність, оскільки в аргументах були також бібліотеки GTK та GNOME.

Отже, єдине пояснення для мене полягає в тому, що це повідомлення могло бути призначене вам допомогти , але воно не зробило це належним чином. Напевно, це було просто: бібліотека, яка надає символ, не була додана до командного рядка.

Зверніть увагу на три важливі правила щодо зв’язку в POSIX:

  • Динамічні бібліотеки мають визначені залежності, тому лише бібліотеки з верхньої залежності повинні постачатися в будь-якому порядку (хоча після статичних бібліотек)
  • Статичні бібліотеки мають лише невизначені символи - ви самі повинні знати їх залежності та надавати їх у командному рядку
  • Порядок у статичних бібліотеках завжди: спочатку запитувач , слід за провайдером . Інакше ви отримаєте невизначене символьне повідомлення, як і коли ви забули додати бібліотеку до командного рядка
  • Коли ви вказуєте бібліотеку -l<name>, ви ніколи не знаєте, чи це займе lib<name>.soабо lib<name>.a. Динамічна бібліотека є кращою, якщо вона знайдена, а статичні бібліотеки можуть бути застосовані лише за допомогою параметра компілятора - ось і все. І чи є у вас проблеми, як описано вище, це залежить від того, чи були у вас статичні чи динамічні бібліотеки
  • Ну, іноді залежностей може не вистачати в динамічних бібліотеках: D

Він не тільки покликаний допомогти вам, він вимагає, щоб лінкер вирішив імена, про які йдеться. Помилка повністю допустима. Якби компілятор вирішив пропустити це, ви просто отримаєте сегмент за доступом до того, чого немає у двійковій програмі.
kevr

1
Додамо, можливо, що на різних платформах джерело компілюється по-різному; те, що пов'язано в одній системі, не може бути пов'язане в іншій. Зазвичай це не так, але це 100% правдоподібно.
kevr

Проблема полягає не в тому, що це невірно, а в тому, що не зовсім корисно знайти причину проблеми.
Ethouris

7

Я виявив, що у мене така ж помилка. Я складав код і з лапаком, і з бласом. Коли я перейшов наказ про те, що дві бібліотеки були названі, помилка пішла.

"LAPACK_LIB = -llapack -lblas" працював там, де "LAPACK_LIB = -lblas -llapack" видав описану вище помилку.


9
Я отримую цю помилку в проекті, визначеному cmake ... так чи є помилка в Cmake, яка неправильно ставить порядок лінкера?
петер карасев

відповівши на @peterkarasev: спробуйте використовувати find_package(Threads)іtarget_link_libraries( ... ${CMAKE_THREAD_LIBS_INIT})
activedecay

7

Я також зіткнувся з тією ж проблемою. Я не знаю чому, я просто додаю -lpthreadваріант до компілятора і все нормально.

Старий:

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

отримав наступну помилку. Якщо я додаю -lpthreadваріант до вищевказаної команди, тоді ОК.

/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

Це працювало для мене; Мені довелося додати другу, "зайву" -lpthread до команди g ++ у makefile, який робить посилання. (Він уже з'являвся один раз у списку LIBS у makefile.) Я також додав "-L / lib / x86_64-linux-gnu" до визначення LDFLAGS у makefile.
UserX

2

Я знайшов, що іноді бібліотека, на яку скаржиться лінкер, не є причиною проблеми. Можливо, є розумний спосіб розібратися, де проблема, але це те, що я роблю:

  • Прокоментуйте всі пов'язані бібліотеки в команді link.
  • Очистіть усі.
  • Від’єднуйте бібліотеки в команді посилання одна за одною і переупорядкуйте порядок за необхідності.

@peter karasev: Я зіткнувся з тією ж проблемою з проектом cmake gcc 4.8.2 на CentOS7. Порядок бібліотек у розділі "target_link_libraries" є важливим. Я думаю, що cmake просто передає список такому, як він є, тобто він не намагається відпрацювати правильний порядок. Це розумно - коли ви думаєте про це, cmake не може знати, що таке правильне замовлення, поки посилання не буде успішно завершено.



1

Така ж проблема трапилася і зі мною, коли я distccроблю свій проект c ++; Нарешті я вирішив це export CXX="distcc g++".


1

якщо ви використовуєте cmake та pthreads, спробуйте додати наступні рядки

find_package(Threads)
target_link_libraries(${CMAKE_THREAD_LIBS_INIT})

0

Зі мною трапилось те саме, що я встановлював показник HPCC (включає HPL та кілька інших орієнтирів). Я додав -lmу свій сценарій збірки прапори компілятора, а потім він успішно компілювався.


3
Це не дає відповіді на це конкретне запитання і не дає загальної відповіді для сімейства подібних проблем. Це дуже локалізована відповідь цілком на інше питання .
Герман Дьоппес

0

Якщо ви користуєтеся g++, переконайтеся, що ви не працюєте gccнатомість


3
Чому? Не могли б ви трохи допрацювати?
Іван Івкович

@ IvanIvković добре, gcc - компілятор C, g ++ - компілятор C ++. Хоча C ++ може компілювати C, gcc не може компілювати C ++.
Жан-Марк Циммер

0

Спробуйте додати -pthreadв кінці списку бібліотек у Makefile .

Це працювало для мене.


0

Якщо ви використовуєте CMake, є кілька способів вирішити це:

Рішення 1: Найелегантніший

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

Рішення 2: використання 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})

Рішення 3: Зміна прапорів 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")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.