Как отследить необходимость библиотеки при линковке? - PullRequest
0 голосов
/ 02 февраля 2019

Быстрая версия: почему gcc запрашивает определенную библиотеку?Как отследить его зависимость при выполнении gcc?

Длинная версия: я пытаюсь скомпилировать код c ++, который использует opencv, который использует ffmpeg.При компиляции появляются ошибки:

//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_alloc@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_free@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_is_initialized@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_close@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_init@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_convert@LIBSWRESAMPLE_2' sin definir

Я понимаю, что libavcodec.so нужен libswresample.so, но я ожидаю ссылки на libavcodec.so.58, а не на 57. Я хочу проследить эту зависимость: я хочу знатьпочему gcc запрашивает этот файл.

Я знаю, что было бы лучше иметь в системе только libavcodec.so, но сейчас я не могу избавиться от libavcodec.so.57.В моей системе:

$ ldconfig -p | grep libavcodec
libavcodec.so.58 (libc6,x86-64) => /usr/local/lib/libavcodec.so.58
libavcodec.so.57 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libavcodec.so.57
libavcodec.so (libc6,x86-64) => /usr/local/lib/libavcodec.so  <== This is a link to 58)

Если вы хотите знать, командная строка gcc такова, обратите внимание, что там нет -lavcodec:

g++ -Wl,--trace-symbol=libavcodec -L/usr/local/lib -L"/home/alejandro/Desarrollo eclipse/os1/Thirdparty" -o "os1"  ./src/Converter.o ./src/Frame.o ./src/FrameDrawer.o ./src/Initializer.o ./src/KeyFrame.o ./src/KeyFrameDatabase.o ./src/KeyFrameTriangulacion.o ./src/LocalMapping.o ./src/LoopClosing.o ./src/Map.o ./src/MapDrawer.o ./src/MapPoint.o ./src/ORBextractor.o ./src/ORBmatcher.o ./src/Optimizer.o ./src/PnPsolver.o ./src/PuntoLejano.o ./src/PuntosLejanosDB.o ./src/Sim3Solver.o ./src/System.o ./src/Tracking.o ./src/Video.o ./src/Viewer.o ./src/main.o ./src/osmap.o ./src/osmap.pb.o   -lopencv_core -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_calib3d -lpthread -lpangolin -lGL -lGLU -lDBoW2 -lg2o -lprotobuf

Эта команда запрашивает libopencv_videoio.so, котораяв свою очередь следует искать libavcodec.so.58.Сканирование всех общих объектов opencv:

& ldd -r /usr/local/lib/libopencv_*.so | grep libavcodec
libavcodec.so.58 => /usr/local/lib/libavcodec.so.58 (0x00007f0f03c11000)
libavcodec.so.58 => /usr/local/lib/libavcodec.so.58 (0x00007fb00e3fa000)
libavcodec.so.58 => /usr/local/lib/libavcodec.so.58 (0x00007f916be48000)

Бонус: почему я не могу удалить libavcodec.so.57

Используя Synaptic, этот файл принадлежит libavcodec-extra57пакет.Когда я удаляю его, Synaptic автоматически устанавливает пакет libavcodec57.Если я удаляю его, первый переустанавливается.Из-за множества зависимостей, нуждающихся в этой библиотеке.Если кто-то захочет поделиться быстрым способом исправить это, я буду признателен.

Спасибо за ваше время.

Если вам интересно, вот длинный вывод gcc --trace,У меня был другой, более длинный с -v -Wl, -v, очень похожий на этот, но без какого-либо нового упоминания о libavcodec.

$ g++ -Wl,--trace -L/usr/local/lib -L"/home/alejandro/Desarrollo eclipse/os1/Thirdparty" -o "os1"  ./src/Converter.o ./src/Frame.o ./src/FrameDrawer.o ./src/Initializer.o ./src/KeyFrame.o ./src/KeyFrameDatabase.o ./src/KeyFrameTriangulacion.o ./src/LocalMapping.o ./src/LoopClosing.o ./src/Map.o ./src/MapDrawer.o ./src/MapPoint.o ./src/ORBextractor.o ./src/ORBmatcher.o ./src/Optimizer.o ./src/PnPsolver.o ./src/PuntoLejano.o ./src/PuntosLejanosDB.o ./src/Sim3Solver.o ./src/System.o ./src/Tracking.o ./src/Video.o ./src/Viewer.o ./src/main.o ./src/osmap.o ./src/osmap.pb.o   -lopencv_core -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_calib3d -lpthread -lpangolin -lGL -lGLU -lDBoW2 -lg2o -lprotobuf
/usr/bin/ld: modo elf_x86_64
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o
./src/Converter.o
./src/Frame.o
./src/FrameDrawer.o
./src/Initializer.o
./src/KeyFrame.o
./src/KeyFrameDatabase.o
./src/KeyFrameTriangulacion.o
./src/LocalMapping.o
./src/LoopClosing.o
./src/Map.o
./src/MapDrawer.o
./src/MapPoint.o
./src/ORBextractor.o
./src/ORBmatcher.o
./src/Optimizer.o
./src/PnPsolver.o
./src/PuntoLejano.o
./src/PuntosLejanosDB.o
./src/Sim3Solver.o
./src/System.o
./src/Tracking.o
./src/Video.o
./src/Viewer.o
./src/main.o
./src/osmap.o
./src/osmap.pb.o
-lopencv_core (/usr/local/lib/libopencv_core.so)
-lopencv_features2d (/usr/local/lib/libopencv_features2d.so)
-lopencv_highgui (/usr/local/lib/libopencv_highgui.so)
-lopencv_videoio (/usr/local/lib/libopencv_videoio.so)
-lopencv_imgcodecs (/usr/local/lib/libopencv_imgcodecs.so)
-lopencv_imgproc (/usr/local/lib/libopencv_imgproc.so)
-lopencv_calib3d (/usr/local/lib/libopencv_calib3d.so)
/lib/x86_64-linux-gnu/libpthread.so.0
-lpangolin (/usr/local/lib/libpangolin.so)
-lGL (/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libGL.so)
-lGLU (/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libGLU.so)
-lDBoW2 (/home/alejandro/Desarrollo eclipse/os1/Thirdparty/libDBoW2.so)
-lg2o (/home/alejandro/Desarrollo eclipse/os1/Thirdparty/libg2o.so)
-lprotobuf (/usr/local/lib/libprotobuf.so)
-lstdc++ (/usr/lib/gcc/x86_64-linux-gnu/7/libstdc++.so)
/lib/x86_64-linux-gnu/libm.so.6
/lib/x86_64-linux-gnu/libmvec.so.1
/lib/x86_64-linux-gnu/libmvec.so.1
libgcc_s.so.1 (/usr/lib/gcc/x86_64-linux-gnu/7/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/lib/gcc/x86_64-linux-gnu/7/libgcc_s.so.1)
/usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_alloc@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_free@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_is_initialized@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_close@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_init@LIBSWRESAMPLE_2' sin definir
//usr/lib/x86_64-linux-gnu/libavcodec.so.57: referencia a `swr_convert@LIBSWRESAMPLE_2' sin definir
/usr/bin/ld: se encontraron errores de enlace, se borra el ejecutable `os1'
collect2: error: ld returned 1 exit status

Ответы [ 3 ]

0 голосов
/ 02 февраля 2019

Что почти наверняка происходит, так это то, что одной из разделяемых библиотек, которые вы загружаете по очереди, нужна другая разделяемая библиотека.Это закодировано в самой разделяемой библиотеке в заголовке ELF.Используйте readelf -d в общей библиотеке, чтобы увидеть это.Ищите NEEDED строки.ld будет обрабатывать библиотеки, которые он находит таким образом, но они не отображаются в выводе --trace.

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

Когда вы найдете строку NEEDED, обратите особое внимание на то, что именно в ней.Это libavcodec.so или libavcodec.so.57?Это просто имя файла или у него есть абсолютный путь?Это влияет на то, что компоновщик найдет при его поиске.

Путь поиска компоновщика см. В документации по опции rpath-link для ld.Каков первый файл (вероятно, символическая ссылка) с именем libavcodec.so в этом пути?Имейте в виду, что компоновщик ищет то, что появляется в строке НЕОБХОДИМО.Он не собирается сокращать libavcodec.so.57 до libavcodec.so и искать последнее.

0 голосов
/ 03 февраля 2019

После ответа @TrentP стало ясно, что сделать это было нелегко, поэтому я сделал, как он предложил, сложным способом, я зациклился на всех общих объектах, рекурсивно ища зависимости.Я использовал ldd -r вместо readelf.ldd -r рекурсивно перечисляет зависимости (прямые и косвенные).

В текстовом файле я помещаю полный список путей общего объекта, который появился в выводе gcc.Затем запустите:

while read -r line; do echo "Library $line has these dependencies:\n $(ldd -r $line)"; done <textfile.txt

Я нашел libavcodec.so.57 в указанном выводе и обнаружил, какой общий объект нуждался в этом.

0 голосов
/ 02 февраля 2019

Существует два способа решения этой проблемы:

  • Прочтите руководство;всегда хорошая идея.
  • Установите менеджер зависимостей.Я использую MacPorts, но есть несколько разных.У них есть база данных библиотек, которыми они управляют, и когда вы устанавливаете или собираете одну из их библиотек, менеджер также установит или соберет все библиотеки, от которых зависит, какая из них вы устанавливаете, и еслите, от которых они зависят и т.д.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...