Could not find a package; ld returned 1 exit status;error while loading shared libraries

关于CMakeLists.txt中find_packge()和动态库查找的遇到的大部分问题总结

前段时间,一直在编译代码,遇到一些关于cmake中编译的相关问题,想着经下心来总结以下相关问题,发现深挖后,真是理解到了学无止境,还有很多东西需要了解,不过在其中也总结了一些东西想要分享给大家,有什么问题可以及时沟通。

下面主要从两个方面介绍cmake中的查找默认路径和方式,以及我们能够做的工作,下面介绍的这是其中的一小部分,让我用简短的一段文字完全讲述其中的相关知识背景,我实在无能为力,此外由于知识水平有限,其中会有我的知识瓶颈,如有不同观点,欢迎沟通交流,互相成长!

常见报错形式:
以下3个报错,为常见错误。

  1. Could not find a package configuration file provided by “XXX” with any of the following names:
    原因:没有找到你的功能包,其实是没有找到.cmake文件,可以采用1.1.1中的最后一个针对配置模式的解决方案,就可以解决了。
  2. error: ld returned 1 exit status。
    原因:ld是链接器的简称,所以是链接是没有找到这个库文件,一般为编译时,没有找到库的地址,可以通过添加下面代码,让ld找到库文件,括号内的地址是你的库文件存放的地址,这个问题解决后,可能会出现3中出现的问题,找到了链接不上,我还没有解决此问题,欢迎讨论。不过还是可以通过1.1.2.1中的其中一个方法解决此问题的。
link_directories(${PROJECT_SOURCE_DIR}/bin/)
  1. error while loading shared libraries: libSatp.so.1: cannot open shared object file: No such file or directory。
    原因:这种情况一般是编译通过后,运行时报的错误,编译没有报错误,说明这个包存在,并且找到了,就是没有链接上,采用1.1.2.1中的任意一个一般可以解决,没有解决可以沟通交流。但是我困惑的是想要通过1.1.2.2中提出的方式解决,一直没有成功,报这个错误,我很困惑一直没有解决。

1 不同方式引入的库

在我目前知识范围内,自己编译环境存在的库的形式大致可以分为两大类,一种是自己编译环境下通过cmake/make由源码编译生成的库文件另外一种是在别人电脑编译生成库文件后,拷贝到自己环境中的,此时特指只拷贝了库文件,没有拷贝源码,如果拷贝了源码,在自己环境中进行再次编译生成动态库就和第一中情况一样了。以上库文件,一般指动态链接库和静态链接库,其中动态链接库(有的称为共享库)unbuntu下常以.so结尾,静态链接库以.a结尾。

以上两种方式引入的动态库,在我们编写CmakeLists.txt时的引用方式不同,具体引用方式如何书写,此文章暂时不进行分享,以后了解更多了再写。此文章重点书写在链接过程中出现链接失败,如何使编译通过。

1.1 通过编译引入的库

通过编译引入的动态库,一般make都会生成一个Config.cmake文件,如果提示查找不到某个包(can not find package),你就可以在根目录下搜索一下有没有这个文件,有的话,直接把这个地址给find_pkg 就行了,此方式也可以指定你想要选择的包版本。具体是如何查找的,以及查找路径可以看下面的讲解。

1.1.1 findpackage查找路径
  1. 模块模式

    cmake的模块模式,我理解的就是cmake编译时查找你想要引入的库的Find.cmake文件

    1) 首先查找当前cmake 路径下的所有目录中是否存在你想引入库的Find.cmake,此文件一般为用户自定义的。

    2)如果没有查找到,cmake一般会在/usr/share/cmake-x.y/Modules/中查找,此文件夹中的Find.cmake为cmake 官方给出专门查找功能包的文件,其中的一个Find.cmake可以找到一个对应的功能包,其中只是一部分常用功能包。

    如果官方给出了某个功能包的Find.cmake文件,你就可以在cmakelist.txt中通过find_package(XXX)引入此功能包。

  2. 配置模式

    cmake在模块模式中如果没有查找到对应的库,将会进入配置模式,我目前理解的配置模式就是查找
    <包名>Config.cmake

    1) 首先会在~/.cmake/packages中查找是否有你引入的 <包名>Config.cmake,我查看的我的电脑这个目录中没有什么东西。

    2) 然后会在/usr/local/share/中查找是否存在你想要引入的 <包名>Config.cmake

  3. 根据模块模式和配置模式我们可以做什么?

    知道了模块模式和配置模式的查找方式后,我们就可以使用这些规则制定我们自己的Find.cmake<包名>Config.cmake了。

    1)针对模块模式,我们可以在自己当前cmake目录下,编写Find.cmake文件,指定引入的库的路径。

    下面是编写的find_qt.cmake文件示例。

    if (WIN32)
    # set stuff for windows
    #    SET(Qt5_PATH /path/to/your/qt/lib)
    else()
    # set stuff for other systems
     SET(Qt5_PATH /home/wsb/Qt5.12.2/5.12.2/gcc_64/lib/cmake/Qt5/)
    #此处被更改,更改为本机QtConfig.cmake的地址
    endif()
    
    SET(CMAKE_PREFIX_PATH ${Qt5_PATH})
    
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTORCC ON)
    set(CMAKE_AUTOUIC ON)
    
    if(CMAKE_VERSION VERSION_LESS "3.7.0")
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    endif()
    
    #set(Qt5 /home/wsb/Qt5.12.2/5.12.2/gcc_64/lib/cmake/Qt5/)
    #此处为添加内容,为本机QtConfig.cmake的地址,与上处可替换
    find_package(Qt5 COMPONENTS Core Network RemoteObjects REQUIRED)
    
    include_directories(${Qt5Core_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS})
    

    2)针对配置模式,如果我们想要指定某一个库的版本,例如有多个OpenCVd的版本,我们需要先在本机找到需要版本的 <包名>Config.cmake
    然后在CMakeLists.txt中添加以下代码,"/usr/local/share/OpenCV/"路径为我需要的OpenCV的OpenCVConfig.cmake的地址。

    set(OpenCV_DIR "/usr/local/share/OpenCV/")
    #指定自己需要的OpenCV的版本
    find_package(OpenCV REQUIRED)
    

1.1.2 通过单独复制引入的库

其中有一些库并不是通过make源码安装的,我遇到的情况是,我购买了摄像头,供应商给我提供的一些 动态库(.so文件),这些动态库是零散的,
无法通过上面提到的模块模式和配置模式完成引入库的功能,cmake 还提供了一些单独查找库的方法。

1.1.2.1 几种从系统中角度引入单个动态库的方法
  1. export LD_LIBRARY_PATH=/usr/lib64/(/usr/lib64/为 .so所在路径),只对当前用户的终端生效,其他用户没用。

  2. 在 /etc/ld.so.conf文件下,找一个文件将动态库的路径加进来,然后 执行sudo /sbin/ldconfig 进行更新。

  3. 无论什么动态库, Linux操作系统,都是默认去该目录下 /usr/lib/查找使用的动态库,所以有两种办法。

    1)创建动态库的软连接至该目录;sudo ln -s (动态库的源文件) /usr/lib。这个方法的好处是动态库进行更新时,会把目录下的一起更新,不需要额外操作。

    2)sudo cp (动态库的源文件) /usr/lib;(不推荐把动态库拷贝至该目录下 ,因为更新时需要把该目录下的都重新拷贝)

  4. 修改该用户下的 .bashrc 配置文件;将动态库的路径添加进来;重新执行配置文件:source .bashrc。(弊端:只 在当前用户下有用)

1.1.2.2 如何通过CMakeLists.txt引入单个动态库?

最近一直被在各个问题困惑,还没有搞清楚怎么回事,前面的几种方式都是在系统中添加自己的库文件,怎么有一种方式,不需要通过系统,直接在CMakeLists.txt中引入单个库,这样就不用每次对系统都进行更改某些内容了,有知道的朋友,可以与我分享一下。我尝试以下代码引入,单个动态库,同一个文件中的动态库,有的被成功链接到,有的就是链接不会上,不知道怎么回事?

#添加头文件地址
include_directories(
  ${catkin_INCLUDE_DIRS}
  ${OpenCV_INCLUDE_DIRS}
  ${PROJECT_SOURCE_DIR}/include/
)
#添加库文件地址
link_directories(${PROJECT_SOURCE_DIR}/bin/)
#多个库赋值到STECAM_LIBS变量中
set(STECAM_LIBS StereoCamera  Satp icudata icui18n icuuc ImageUtils QAsioSocket Qt5Core Qt5Gui Qt5Network Qt5RemoteObjects  SatpExt)
#创建可执行文件
add_executable(stereo_publisher
        src/stereo_publisher.cpp
        src/framemonitor.cpp
        src/pointcloudgenerator.cpp
        )
 #添加链接库
target_link_libraries(stereo_publisher
        ${catkin_LIBRARIES}
        ${STECAM_LIBS}
        )
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值