首页 > 系统相关 >linux下通过rpath解决cmake动态编译后找不到动态链接库问题

linux下通过rpath解决cmake动态编译后找不到动态链接库问题

时间:2022-11-22 19:36:32浏览次数:39  
标签:set cmake lib rpath 编译 so linux project1 目录

通过cmake编译链接动态库后,会有一个问题,那就是需要的.so文件不能更改目录,一旦.so文件目录变了,整个程序就没法运行了,这肯定是不行的。

原因

后来我查一下一下,linux系统中,程序加载运行需要的.so文件是有顺序的

  1. 环境变量LD_LIBRARY_PATH指定的路径
  2. gcc 编译时指定的运行时库路径-rpath
  3. ldconfig 配置文件ld.so.conf指定的路径
  4. 系统默认库位置 /lib, /usr/lib

如果没有指定so的位置,gcc会自动把当前so所在的目录作为so的连接目录。知道原因了,问题就好解决了

解决办法

先看一下现在的 CMakeLists.txt文件

cmake_minimum_required(VERSION 3.13.3)
project(project1 C)

set(CMAKE_C_STANDARD 99)

add_library(shared SHARED library.h library.c)

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

add_executable(project1 main.c)

target_link_libraries(project1 shared)

我实验了两种办法,一是把.so 文件放到/lib 或者 /usr/lib中,这也是在安装很多软件时的做法,当使用包管理器安装软件时,需要的.so文件大多是安装到这两个目录下。在一种就是在编译时指定 rpath的目录,使用相对目录,这样在复制文件的时候,把.so一起复制就可以了。

先用最简单的办法,把so目录放到系统目录下
   

现在的目录结构如下,程序依赖的libshared.solib 目录下,现在把 libshared.so 复制到 /lib 目录下。这里有个要注意的地方,复制完后要执行 ldconfig 命令,重新生成缓存,要不然程序依然找不到对应的.so文件
命令如下

  1. sudo mv lib/libshared.so /lib
  2. sudo ldconfig

这时候在运行 project1 不会报错

编译时指定 rpath目录

设置 rpaht 有两种方式

方式1

set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH $ORIGIN)

通过修改编译后的 install 路径, 让程序在运行时通过程序的相对目录加载.so文件,其中 $ORIGIN 变量是程序的当前目录

方式2

set_target_properties(project1 PROPERTIES LINK_FLAGS "-Wl,-rpath,./")

方式2更粗暴,直接设置gcc的编译参数,指定rpaht 是当前目录

修改 CMakeLists.txt文件

cmake_minimum_required(VERSION 3.13.3)
project(project1 C)

set(CMAKE_C_STANDARD 99)

add_library(shared SHARED library.h library.c)

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

#方式1
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH $ORIGIN)

add_executable(project1 main.c)

#方式2
#set_target_properties(project1 PROPERTIES LINK_FLAGS "-Wl,-rpath,./")
target_link_libraries(project1 shared)

重新生成 MakeFile 文件, 然后编译

编译生成的 libshared.so 还是在 lib目录下,先移动到可执行文件的同级目录下

   

 

最终目录如图,现在无论怎么复制文件,只要可执行文件和动态库在一个目录下,都以运行了

总结

解决linux下 动态编译的程序找不到动态库的问题,有多种解决办法,这次用了两种

  1. 把需要的.so文件放到 /lib 或者 /usr/lib 下, 然后执行 ldconfig命令
  2. 通过指定 rpath 来决定加载 .so的目录


ref:https://www.jianshu.com/p/9b086881c423

标签:set,cmake,lib,rpath,编译,so,linux,project1,目录
From: https://www.cnblogs.com/lidabo/p/16916183.html

相关文章

  • Linux C编程 使用相对路径加载动态库-rpath和$ORIGIN
    商业程序如何加载自己的so使用LD_LIBRARY_PATH的缺点是要实现设置LD_LIBRARY_PATH。不够自动化。那么大型的商业程序是如何加载自己的so呢。这里以QtCreator为例。QtC......
  • 【linux基础(二)】Linux文件(目录)命名规则
    在Linux系统中,一切都是文件,既然是文件,就必须要有文件名。同其他系统相比,Linux操作系统对文件或目录命名的要求相对比较宽松。Linux系统中,文件和目录的命名规则如下:除......
  • 使用cmake构建C/C++项目和动态库
    编译C/C++文件时,很多时候都是直接使用像gccmain.c或者g++main.cpp这样的命令编译的。但是代码文件多了后,这样编译就很困难了。这时候就出现了MakeFile这个工具。......
  • chroot恢复Arch Linux
    这篇速成指南诠释了一些步骤,它对于恢复一个Arch ​​Linux 安装很有帮助。作为一个滚动发布版本,ArchLinux有时会崩溃。那不是你自身的问题,而是因为数百个其它的原因,例......
  • 中科大嵌入式linux课程笔记01
    lesson1嵌入式系统主要概念课程简介课程目录参考书嵌入式系统结构和开发流程概念、特点、组成、硬件、软件、开发​ 嵌入式系统首先是一个计算机系统,后者有的技......
  • Linux 安装Docker 一键脚本执行
    sudoyumremovedocker*sudoyuminstall-yyum-utils#配置docker的yum地址sudoyum-config-manager\--add-repo\http://mirrors.aliyun.com/docker-ce/linux/c......
  • linux上部署皕杰报表小结
    最近需要在一个服务器上部署皕杰报表,连接的是mysql的库。步骤如下:1.首先先下载jdk,配置相应的Java环境。2.下载mysql,上官网下载相应的rpm包。3.安装好mysql后,使用dbeaver工具......
  • linux中已启动tomcat,网页无法访问
    使用./catalina.shrun提示以下错误:  在/home目录下并没有找到jre的相关目录解决:在/etc/profile中将jre_home=$JAVA_HOME然后source/etc/profile,就可以了......
  • Linux程序编译过程详解
    大家肯定都知道计算机程序设计语言通常分为机器语言、汇编语言和高级语言三类。高级语言需要通过翻译成机器语言才能执行,而翻译的方式分为两种,一种是编译型,另一种是解释型,因......
  • Linux基础命令
    用户、组useraddrbcuserdel-rrbcusermod-grbc-Ghadoop,hiverbc用户附加组可以多个idrbcgroupaddsharegroupdelsharechown......