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'. Системное сообщение об ошибке: слишком много уровней символических ссылок
Ашиш Карпе


4
Черт возьми, я gccнеg++
Post Self

Ответы:


164

Вы должны упомянуть библиотеку в командной строке после компиляции объектных файлов:

 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требуется символ from libcи libcнужен символ from libb, командная строка должна быть:

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

24
Я думаю, что вы можете сделать -Wl,--start-group -la -lb- -lc -Wl,--end-groupдля круговых зависимостей.
Z бозон

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 :(. Text + 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,бит, либо у вас есть компоновщик, который не поддерживает эти опции. Какой линкер вы используете? Этот ответ предполагает классический линкер binutils (ld.bfd). Золотой компоновщик binutils (ld.gold) помечается --copy-dt-needed-entriesкак «Не поддерживается». Поэтому, если у вас есть это (или любой другой компоновщик, который не поддерживает эту опцию) по умолчанию, вам может потребоваться следовать разделу для сопровождающих или перейти на классический ld для компоновки. Я думаю, что вы можете использовать -fuse-ld=ld.bfdдля этого.
текстовая оболочка

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

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

Итак, единственное объяснение для меня - это то, что это сообщение могло помочь вам , но оно не сделало это должным образом. Вероятно, это было просто: библиотека, предоставляющая символ, не была добавлена ​​в командную строку.

Обратите внимание на три важных правила, касающихся связи в POSIX:

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

Он предназначен не только для того, чтобы помочь вам, но и для того, чтобы компоновщик разрешил указанные имена. Ошибка полностью действительна. Если бы компилятор решил пропустить это, вы бы просто получили segfault для доступа к чему-то, чего нет во время выполнения двоичного кода.
kevr

1
Можно добавить, что на разных платформах исходный код компилируется по-разному; то, что связано в одной системе, может не быть связано в другой. Обычно это не так, но это на 100% правдоподобно.
kevr

Проблема не в том, что это не правильно, а в том, что не совсем полезно найти причину проблемы.
Ethouris

7

Я обнаружил, что у меня была такая же ошибка. Я компилировал код с использованием lapack и blas. Когда я сменил порядок именования двух библиотек, ошибка исчезла.

«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 ++ в make-файле, который делает ссылку. (Он уже один раз появился в списке LIBS в make-файле.) Я также добавил «-L / lib / x86_64-linux-gnu» в определение LDFLAGS в make-файле.
UserX

2

Я обнаружил, что иногда библиотека, на которую жалуется компоновщик, не та, которая вызывает проблему. Возможно, есть умный способ решить, где проблема, но это то, что я делаю:

  • Закомментируйте все связанные библиотеки в команде link.
  • Очистите все .o, .so и т. Д. (Обычно достаточно сделать clean, но вы можете запустить рекурсивный поиск + rm или что-то подобное).
  • Раскомментируйте библиотеки в команде 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.