我没有改变项目的cmake
配置,唯一改变的是新版本开源库(OpenCV)的“内部”构建版本,奇怪的是,本地提取文件夹中的一些库被链接并找到,而其他库没有。
- 调用cmake时,将创建包含所有所需库的
OPENCV_LIB
变量-此变量用于链接 - 所有此类库都存在于文件夹中
- 整个库一步构建完成(均适用于x64配置)
- 项目与库中的库正确链接
然而,当在最终的可执行文件上调用ldd
时,结果是相当混乱的。
libopencv_core.so.406 => /LOCAL_FOLDER/OpenCV/lib/x64/libopencv_core.so.406 (0x00007f974e2df000)
libopencv_calib3d.so.406 => /LOCAL_FOLDER/OpenCV/lib/x64/libopencv_calib3d.so.406 (0x00007f974d852000)
libopencv_imgcodecs.so.406 => /LOCAL_FOLDER/OpenCV/lib/x64/libopencv_imgcodecs.so.406 (0x00007f974d795000)
libopencv_imgproc.so.406 => /LOCAL_FOLDER/OpenCV/lib/x64/libopencv_imgproc.so.406 (0x00007f974b79c000)
libopencv_features2d.so.406 => not found
libopencv_flann.so.406 => not found
所有库都存在于用于链接的OPENCV_LIB
变量中,并且所有库都存在于LOCAL_FOLDER
中。当对库调用ldd
时,会导致not found
出现在LOCAL_FOLDER
中,同时未找到它们的某些依赖项。当它们来自同一文件夹时,为什么会找到某些库而找不到某些库?
OpenCV库包含到项目中的过程:
脚本创建dependencies.cmake
文件,该文件随include(dependencies.cmake)
一起提供。该文件包含以下行:
set(OPENCV_INCLUDE_DIR "/LOCAL_FOLDER/OpenCV/include")
include_directories(${OPENCV_INCLUDE_DIR})
link_directories("/LOCAL_FOLDER/OpenCV/lib/x64/")
set(OPENCV_LIB ${OPENCV_LIB} *.so) # * as substitution for all the libs that are "set" this way.
然后,在子项目的CMakeLists
中,按如下方式使用
target_link_libraries(${PROJECT_NAME} ${OPENCV_LIB} "-Wl,--disable-new-dtags")
其中一个库的ldd -v
结果
/LOCAL_FOLDER/OpenCV/lib/x64/libopencv_calib3d.so.406:
libgcc_s.so.1 (GCC_3.0) => /lib/x86_64-linux-gnu/libgcc_s.so.1
libgcc_s.so.1 (GCC_4.0.0) => /lib/x86_64-linux-gnu/libgcc_s.so.1
libm.so.6 (GLIBC_2.29) => /lib/x86_64-linux-gnu/libm.so.6
libm.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libm.so.6
libstdc++.so.6 (GLIBCXX_3.4.20) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (CXXABI_1.3.8) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4.19) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4.9) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4.29) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4.26) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4.11) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (CXXABI_1.3) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4.14) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4.21) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4.15) => /lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++.so.6 (GLIBCXX_3.4) => /lib/x86_64-linux-gnu/libstdc++.so.6
libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6
RPATH设置为原点,如下所示
set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN")
我也试过按照帖子here中的建议设置它,但没有什么解决这个问题。
将其显式设置为LOCAL_FOLDER
不会执行任何操作。
当我下载同一个库的旧的“内部”构建版本,并在一些库上调用ldd
,在新的库中显示not found
时,它最终处于相同的情况。链接总是可以的。基本上,对于旧版本的库,ldd
显示的库是相同的。但是生成的二进制文件是可以的(所有库都被正确定位),可以运行没有问题。旧库和新库之间的唯一区别是旧库是用GCC 8和Ubuntu 18构建的。新库是用GCC 11和Ubuntu 20构建的。
2条答案
按热度按时间cetgtptt1#
你已经为你的目标指定了RPATH,所以它的直接依赖项是在程序的目录中搜索的,我认为你的程序直接依赖于libopencv_core.so.406,libopencv_calib3d.so.406,libopencv_imgcodecs.so.406和libopencv_imgproc.so.406。另外两个库是间接依赖关系(即它们是前一个库的直接依赖项)。因此,当搜索这些间接依赖项时,您的程序RPATH不适用。
我建议你这样运行你的程序。
$ LD_LIBRARY_PATH=“密码”./您的程序二进制名
Upd:您还在OPENCV_LIB变量中指定了所有库,链接器抛出其中一些库,因为您的程序不直接使用它们的符号。
您可以通过添加一些对libopencv_features2d.so.406和libopencv_flann.so.406中定义的函数的显式调用,然后运行ldd来检查我的答案。
链接器优化了库列表,因为CMake用
-Wl,--as-needed
参数调用ld。你也可以找出如何关闭这种行为。我不是一个cmake大师来帮助你这样做。wfypjpf42#
问题是新版本的依赖库定义了
RUNPATH
,但使用此库的其他项目/库正在使用RPATH
。定义RUNPATH
时,它将忽略任何已定义的RPATH
。因此传递依赖忽略了RPATH
。解决方案是从新库中删除RUNPATH
并添加RPATH
。RPATH
已经被弃用,所以如果任何人面对这个问题可以使用RUNPATH
而不是RPATH
,他们应该这样做。在this答案的帮助下,完成了从
RUNPATH
到RPATH
的变更。