链接时如何跟踪库的需求?

时间:2019-02-02 14:59:13

标签: c++ linux opencv gcc ld

快速版本:为什么gcc要求特定的库?在执行gcc时如何跟踪其依赖性?

长版本:我正在尝试编译使用opencv的c ++代码,后者使用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 :(得分:2)

几乎可以肯定的是,您依次加载的共享库之一需要另一个共享库。它被编码到ELF标头中的共享库中。在共享库上使用readelf -d可以看到此信息。寻找NEEDED行。 LD将处理它找到这样的库,但它们不会出现在的输出--trace

我不知道的方式,自动寻源,但尽量readelf上会出现在您的跟踪库,你应该找到一个需要libavcodec的,或者需要一个库,轮流需要的libavcodec等

当找到NEEDED行时,请仔细注意其中的确切含义。是libavcodec.so还是libavcodec.so.57?它仅仅是文件名还是具有绝对路径?这会影响到什么时,它会搜索它连接器会找到的。

有关链接器搜索路径,请参阅ld的rpath-link选项的文档。该路径中名为libavcodec.so的第一个文件(可能是符号链接)是什么?请记住,链接器搜索需要行中显示的内容。不会将libavcodec.so.57缩短为libavcodec.so并搜索后者。

答案 1 :(得分:1)

在@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,并检测到哪个共享库需要它。

答案 2 :(得分:-2)

有两种方法可以解决此问题:

  • 阅读手册;总是一个好主意。
  • 安装依赖项管理器。我使用MacPorts,但是有一些 不同的在那里。他们有一个图书馆数据库 他们管理,以及当您安装或构建其中一个 库,经理还将安装或构建所有库 您要安装的那个取决于它们是否还不存在,以及 取决于等等。