librt и неопределенная ссылка на mq_unlink и друзей - PullRequest
0 голосов
/ 07 декабря 2018

У меня есть система, написанная на C ++, которая создает кучу общих библиотек и исполняемых файлов, которые связаны с этими общими библиотеками (и системными библиотеками).Ни один из кодов не использует c ++ 11, только школьный C ++. Весь этот беспорядок поддерживался на старой 32-битной машине SUSE Linux 3.0.13 с GCC 4.3.4.Он поставляется в комплекте с make-файлом, который собирает все.Я нахожусь в процессе переноса всей системы на Ubuntu 16.04 на 64-битном процессоре с gcc 4.8.У меня было несколько проблем с компилятором, но у меня было много времени, чтобы связать вещи.

Все библиотеки общих ресурсов собираются, но когда я пытаюсь создать исполняемый файл, я получаю многоошибок "неопределенная ссылка".Я проверил, что методы и typeinfo из этих ошибок существуют в библиотеках, которые включены в команду ссылки (-l), и что путь к этим библиотекам также включен в команду ссылки (-L).Я даже создал карты компоновщиков и проверил, что классы и методы, обозначенные как «неопределенные», существуют в общих библиотеках.

Мне удается разобраться с некоторыми проблемами «неопределенных ссылок», переупорядочив списокделиться библиотеками в команде link, но я не знаю, почему это будет иметь значение, поскольку те же make-файлы отлично работали на SUSE Linux без необходимости беспокоиться о порядке библиотек.Тем не менее, я все еще застрял на нескольких проектах.Вот один пример:

У меня есть исполняемый файл, который использует общую библиотеку (называемую MQWrapper) для обеспечения оболочки вокруг очередей сообщений Linux.В проекте есть один файл .cpp, который компилируется с помощью следующей команды:

g++ -DZTRACE -DZDEV -I"." -I"../AppIncludes"  -I"../ZediCommon" \
    -I"../NetworkManagerCommon" -I"../TelitModemDriver" -I"../MQWrapper" \
    -I"../Hardware" -I"../WatchdogLib" -I"../BaseClasses" -O0 -g3 -Wall \
    -c -fmessage-length=0 -fPIC -MMD -MP -MF"Debug/NetworkProcess.d" \
    -o "Debug/NetworkProcess.o" "NetworkProcess.cpp"

Это зависит от других общих библиотек, входящих в мою систему.Их местоположение указывается в команде link относительным путем:

g++ -o Debug/networkmanager.1.2.0-DEV  ./Debug/NetworkProcess.o \
   -L../sharedlibs/Debug -lZediCommon -lMQWrapper -lBaseClasses \
   -lorm -lHardware -lWatchdogLib -llog4cplus-1.1 -lNetworkManagerCommon \
   -lpthread -lTelitModemDriver -ldl -lrt 

Как видите, в команде указывается "-lrt".Тем не менее, когда я пытаюсь скомпоновать, я получаю следующие ошибки компоновщика:

../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_unlink'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_close'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_getattr'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_receive'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_open'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_setattr'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_send'

Я убедился, что общая библиотека librt.so существует и находится в пути поиска компоновщика.Я даже создал небольшую тестовую программу, которая использует эти функции, скомпилировал и соединил ее, и она прекрасно сработала.

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

Кто-нибудь знает, почему это может происходить?Может кто-нибудь предложить несколько советов по отладке?Есть ли разница между компоновщиком SUSE и компоновщиком Ubuntu, который может вызывать эти проблемы?


Обновление

Ссылочный пост дает хорошее объяснение процесса компиляции и компоновки и приводит возможные причины, ни один из которых не относится к моей проблеме.Я рассмотрел все предложения.

  1. Я ссылаюсь на правильные библиотеки.В частности, функции очереди сообщений Linux реализованы в librt.so (или, по крайней мере, так должно быть), и в моей команде компоновщика есть -lrt.

  2. Это функции, предоставляемые системой Linux, поэтому«Объявлено, но не определено переменную или функцию» не применяется.Никаких ошибок компилятора, поэтому соответствие прототипов функций из SUSE Linux в Ubuntu Linux.

  3. Я вызываю системные функции Linux, которые предоставляют прототипы функций C.«чисто виртуальный» не применяется

  4. «виртуальные методы должны быть либо реализованы, либо определены как чисто» не применяется.См. 3.

  5. «Не виртуальные участники класса» не применяются.См. 3.

  6. «Распространенная ошибка - забыть указать имя» не применяется.См. 3.

  7. «члены статических данных должны быть определены вне класса в одной единице перевода» не применяется.См. 3.

  8. «Реализация шаблонов не видна» не применяется.См. 3.

  9. «Символы были определены в программе на C и использованы в коде C ++».Не применяется.У mqueue.h есть прототипы функции обёртывания "extern" C ".

  10. Неправильный импорт / экспорт методов / классов между модулями / dll (зависит от компилятора) не применяется.Я работаю над Linux

  11. «Если ничего не помогает, перекомпилируйте».Сделали это ... много раз.

  12. "Шаблоны для подружки ...".См. 3.

  13. «Несовместимые определения UNICODE».Не применяется.

  14. "Когда ваши пути включения отличаются".См. 2.

  15. «Ваша связь использует библиотеки перед объектными файлами, которые к ним относятся».Не тот случай.Командная строка показывает порядок загрузки вещей.Я также попытался изменить порядок.

  16. "Отсутствует" extern "в объявлениях / определениях переменных const (только C ++)".См. 2.

  17. «Различные версии библиотек».Я не связываю файлы, которые не были созданы в рассматриваемой системе.Поскольку я компилирую и связываю системные библиотеки, это не проблема.

  18. «При связывании с общими библиотеками убедитесь, что используемые символы не скрыты».Я нигде не использую "-fvisibility = hidden".

Единственный пост, который мне помог, был предложенный @Lawrence.Использование -v -Wl, -verbose.Он проверил, что компоновщик находит librt.so и загружает его.Теперь, если кто-то может подсказать, почему компоновщик не найдет символы mq_ *.

1 Ответ

0 голосов
/ 07 декабря 2018

"Ваша связь использует библиотеки перед объектными файлами, которые к ним относятся".Не тот случай.Командная строка показывает порядок загрузки вещей.Я также пытался изменить порядок.

Вероятно, это все еще ваша проблема.Ваш случай усложняется тем, что ваши библиотеки, а не объектные файлы зависят от системных библиотек.

Возможно, вам придется упомянуть -lrt в нескольких местах вкомандная строка вашего компоновщика.

...