通俗理解-L、-rpath和-rpath-link编译链接动态库

news2025/2/21 4:18:20

一、参考资料

链接选项 rpath 的应用和原理 | BewareMyPower的博客

使用 rpath 和 rpath-link 确保 samba-util 库正确链接-CSDN博客

编译参数-Wl和rpath的理解_-wl,-rpath-CSDN博客

Using LD, the GNU linker - Options

Directory Options (Using the GNU Compiler Collection (GCC))

交叉编译时–sysroot,-rpath,-rpath-link,-L之间的关系与注意点_交叉编译 sysroot-CSDN博客

二、相关介绍

Linux 动态库查找路径

一个典型的 C/C++ 程序的构建流程是:预处理,汇编,编译,链接。而执行链接的程序其实是 ld,通常编译器比如 GCC 都会自动调用 ld 去进行链接,用户不必关注其中的细节。而 ld 查找动态库的顺序是:

  1. rpath 指定的目录;
  2. 环境变量 LD_LIBRARY_PATH 指定的目录;
  3. runpath 指定的目录;
  4. /etc/ld.so.cache 缓存文件,通常包含 /etc/ld.so.conf 文件编译出的二进制俩别哦(比如 CentOS 上,该文件会使用 include 从而使用 ld.so.conf.d 目录下面所有的 *.conf 文件,这些都会缓存在 ld.so.cache 中)
  5. 系统默认路径,比如 /lib/usr/lib

在编译时若使用 -z nodefaultlib 选项编译,则会跳过 4 和 5。至于 runpath,和 rpath 类似,都是二进制(ELF)文件的动态 section 属性(分别为 DT_RUNPATHDT_RPATH),唯一区别就是是否优先于 LD_LIBRARY_PATH 来查找。

rpath vs. runpathrpathrunpath 是嵌入在可执行文件或共享库中的路径列表,用于指定运行时查找共享库的位置。rpath 是旧标准,runpath 是新标准,功能类似但优先级不同。

-Wl参数

gcc的-Wl,xxx选项将逗号分隔的标记列表(flags)作为空格分隔的参数列表传递给链接器,即:

gcc -Wl,aaa,bbb,ccc

最终变成了linker的用法:

ld aaa bbb ccc

如果是想把ld -rpath通过-Wl传递给gcc,可以是-Wl,-rpath,xxx,也可以指定-Wl的重复实例:

gcc -Wl,aaa -Wl,bbb -Wl,ccc

类似的参数还有:

-Wa,<options>   Pass comma-separated <options> on to the assembler
-Wp,<options>   Pass comma-separated <options> on to the preprocessor
-Wl,<options>   Pass comma-separated <options> on to the linker 

--sysroot 选项

--sysroot = dir 将dir作为逻辑root目录,用于搜索头文件和依赖库文件,例如 --sysroot=/home/build,那么如果之前默认去 /usr/lib下面去搜索依赖库,则在sysroot的作用下会定位到 /home/build/usr/lib 目录下进行搜索。这个参数在交叉编译的时候会影响到rpath,如果没有设置这个sysroot,则rpath在编译阶段是不起作用的。

在交叉编译工具中,有默认的 sysroot 路径。

# 设置交叉编译工具链的环境变量
export PATH=/home/yoyo/360Downloads/toolchains/arm-linux-gnueabihf/bin:$PATH

# 查看交叉编译工具链的 sysroot 路径
arm-linux-gnueabihf-gcc -print-sysroot

输出示例:

yoyo@yoyo:~$ arm-linux-gnueabihf-gcc -print-sysroot
/home/yoyo/360Downloads/toolchains/arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc

$ORIGIN 变量

关于Linux上的$ORIGIN解说

关于Linux上的$ORIGIN解说

许多现代C / C ++项目都利用 Autotools 创建GNU构建系统,例如根据平台生成make文件。 可执行文件(二进制文件)在生成/编译过程中生成,并且可以在执行编译的计算机上本地执行。 但是,如果将同一可执行文件移动到另一台计算机上,或者只是移到同一台计算机上的其他文件夹,则在运行该可执行文件时可能会遇到“找不到库”错误。因此,引入一个特殊的环境变量 $ORIGIN

在Linux系统中,$ORIGIN 是一个特殊的环境变量,表示可执行文件或共享库所在的目录。使用 $ORIGIN 可以指定相对于可执行文件或共享库的路径,确保程序在不同目录中运行时能正确找到依赖库。

使用 $ORIGIN 的好处在于,它允许可移植性更高的应用程序部署,因为这意味着应用程序和它的依赖库可以被放置在文件系统中的任意位置,并且在运行时动态链接器仍然能正确找到它们,只要维持相对结构不变即可。

简单示例:假设有一个可执行文件 /app/bin/myprogram,依赖库在 /app/lib 中。可以在编译时设置 RPATHRUNPATH$ORIGIN/../lib,这样程序运行时会在 /app/lib 中查找依赖库。

/app/
    myprogram.c
    bin/
    	app
    lib/
        libdependency.so

在链接 app 时,可以使用:

gcc -Wl,-rpath,'$ORIGIN/../x264/lib' -Wl,rpath,'$ORIGIN/../x265/lib' -o app myprogram.c
-Wl,-rpath,'$ORIGIN'

如果需要设置多个路径,可以将它们用空格分隔,并确保每个路径前都有 -Wl,-rpath,

-Wl,-rpath,'$ORIGIN/../third_party/arm_opencv/3rdparty/zlib/lib' \
-Wl,-rpath,'$ORIGIN/../third_party/arm_opencv/3rdparty/szlib/lib'

这样,不管 /usr/appdir/ 复制到文件系统的哪个地方,执行 app 时,libdependency.so 都会从执行文件所在目录下的 lib 目录中被找到和加载。

在处理诸如需要将应用打包到一个单一文件夹以实现便携式部署的情况下,$ORIGIN 变量异常有用。使用 $ORIGIN ,开发者便无需担心程序部署后动态链接库的路径问题,从而大大提高了软件的移植性和灵活性。

注意事项

  • $ORIGIN 必须用引号括起来,防止被 shell 解释。
  • 使用 $ORIGIN 时,确保路径设置正确,避免运行时找不到库。
  • Makefile 或其他文件中直接使用时,只用一个 $ 会展开成变量值,通常需要写作 $$ORIGIN来避免变量扩展。

三、-L、-rpath-link和-rpath

通过使用 rpathrpath-link,可以确保程序在运行时正确找到依赖的库。这对于处理不在系统默认路径下的库非常有用。在编译和链接时正确使用这两个选项可以确保你的程序在不同环境中都能正常运行。

引言

现代连接器在处理动态库时将链接时路径(Link-time path)运行时路径(Run-time path) 分开,用户可以通过 -L指定连接时库的路径,通过-R(或-rpath)指定程序运行时库的路径,大大提高了库应用的灵活性。

-rpath-rpath-link之间的区别:-rpath选项指定的目录被包含在可执行文件中并在运行时使用,而-rpath-link选项仅在链接时有效。

通过测试发现,-Wl,-rpath下面这三种写法都是可以的:

-Wl,-rpath -Wl,/usr/lib/gstreamer-1.0
-Wl,-rpath,/usr/lib/gstreamer-1.0
-Wl,-rpath=/usr/lib/gstreamer-1.0

-l 选项

功能:添加需要链接的库文件,如果没有后缀指明动态库还是静态库,则优先使用动态库。

-L选项(编译时路径)

功能:-L 指定的是编译时链接的动态库搜索路径。

编译时-L选项并不影响环境变量 LD_LIBRARY_PATH,只是指定了程序编译连接时库的路径,并不影响程序执行时库的路径。当程序运行时,系统还是会到默认路径下查找该程序所需要的库,如果找不到,会出现类似 cannot open shared object file 的错误。

-L/mylib -lmylib

-Wl,-rpath选项(运行时路径)

功能:-Wl,-rpath 用于指定动态库的搜索路径(在运行阶段),该路径会被记录在elf可执行文件中。

-rpath 的作用相当于在程序运行时设置了 LD_LIBRARY_PATH 环境变量,因为 -rpath指定的路径会被记录在生成的可执行程序中,用于运行时查找需要加载的动态库 。因此,在开发板中无需设置环境变量即可找到相关的动态库。通常情况下,推荐使用 -Wl,-rpath 选项。

# 单个路径
-L/mylib -lmylib -Wl,-rpath=dir

# 多个路径
-L/mylib -lmylib -Wl,-rpath,dir1:dir2:...:dirN

在cmake中使用:

# 设置第三方库路径
set(3RDPARTY_DIR "${PARENT_DIR}/third_party")

# 设置目标属性,将运行时库搜索路径添加到目标
set_target_properties(
    dla_detect
    PROPERTIES
    LINK_FLAGS
    "-L${3RDPARTY_DIR}/zlib/lib -Wl,-rpath,'$ORIGIN/../../third_party/zlib/lib' \
    -L${3RDPARTY_DIR}/szlib/lib -Wl,-rpath,'$ORIGIN/../../third_party/szlib/lib' \
    -L${3RDPARTY_DIR}/hdf5/lib -Wl,-rpath,'$ORIGIN/../../third_party/hdf5/lib' \
    -L${3RDPARTY_DIR}/x264/lib -Wl,-rpath,'$ORIGIN/../../third_party/x264/lib' \
    -L${3RDPARTY_DIR}/x265/lib -Wl,-rpath,'$ORIGIN/../../third_party/x265/lib' \
    -L${3RDPARTY_DIR}/ffmpeg/lib -Wl,-rpath,'$ORIGIN/../../third_party/ffmpeg/lib' \
    -L${3RDPARTY_DIR}/sigmastar/lib -Wl,-rpath,'$ORIGIN}/../../third_party/sigmastar/lib' \
    -L${3RDPARTY_DIR}/arm_opencv/lib -Wl,-rpath,'$ORIGIN/../../third_party/arm_opencv/lib' \
    -L${PARENT_DIR}/build -Wl,-rpath,'$ORIGIN/../../build'"
)

或者:

# 设置第三方库路径
set(3RDPARTY_DIR "${PARENT_DIR}/third_party")

# 设置rpath
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \
-L${3RDPARTY_DIR}/zlib/lib -Wl,-rpath,'$ORIGIN/../../third_party/zlib/lib' \
-L${3RDPARTY_DIR}/szlib/lib -Wl,-rpath,'$ORIGIN/../../third_party/szlib/lib' \
-L${3RDPARTY_DIR}/hdf5/lib -Wl,-rpath,'$ORIGIN/../../third_party/hdf5/lib' \
-L${3RDPARTY_DIR}/x264/lib -Wl,-rpath,'$ORIGIN/../../third_party/x264/lib' \
-L${3RDPARTY_DIR}/x265/lib -Wl,-rpath,'$ORIGIN/../../third_party/x265/lib' \
-L${3RDPARTY_DIR}/ffmpeg/lib -Wl,-rpath,'$ORIGIN/../../third_party/ffmpeg/lib' \
-L${3RDPARTY_DIR}/sigmastar/lib -Wl,-rpath,'$ORIGIN/../../third_party/sigmastar/lib' \
-L${3RDPARTY_DIR}/arm_opencv/lib -Wl,-rpath,'$ORIGIN/../../third_party/arm_opencv/lib' \
-L${PARENT_DIR}/build -lsigmastar_vVehicle_det -Wl,-rpath,'$ORIGIN/../../build'")

编译之后,查看rpath:

yoyo@yoyo:~/share/driver/dla_detect$ readelf -d test/build/dla_detect
...
0x0000000f (RPATH)                      Library rpath: [$ORIGIN/../../third_party/zlib/lib:$ORIGIN/../../third_party/szlib/lib:$ORIGIN/../../third_party/hdf5/lib:$ORIGIN/../../third_party/x264/lib:$ORIGIN/../../third_party/x265/lib:$ORIGIN/../../third_party/ffmpeg/lib:$ORIGIN/../../third_party/sigmastar/lib:$ORIGIN/../../third_party/arm_opencv/lib:$ORIGIN/../../build:/home/yoyo/share/driver/dla_detect/third_party/arm_opencv/share/opencv4/../../lib]
...

-Wl,-rpath-link选项(运行时路径)

功能:-Wl,-rpath-link 用于指定动态库的搜索路径(在链接阶段),该选项只在链接阶段起作用,不会被写入elf文件中。

-L/mylib -lmylib -Wl,-rpath-link=<library_path>

在cmake中使用:

# 设置第三方库路径
set(3RDPARTY_DIR "${PARENT_DIR}/third_party")

# 设置目标属性,将运行时库搜索路径添加到目标
set_target_properties(
    dla_detect
    PROPERTIES
    LINK_FLAGS
    "-L${3RDPARTY_DIR}/zlib/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/zlib/lib' \
    -L${3RDPARTY_DIR}/szlib/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/szlib/lib' \
    -L${3RDPARTY_DIR}/hdf5/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/hdf5/lib' \
    -L${3RDPARTY_DIR}/x264/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/x264/lib' \
    -L${3RDPARTY_DIR}/x265/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/x265/lib' \
    -L${3RDPARTY_DIR}/ffmpeg/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/ffmpeg/lib' \
    -L${3RDPARTY_DIR}/sigmastar/lib -Wl,-rpath-link,'$ORIGIN}/../../third_party/sigmastar/lib' \
    -L${3RDPARTY_DIR}/arm_opencv/lib -Wl,-rpath,'$ORIGIN/../../third_party/arm_opencv/lib' \
    -L${PARENT_DIR}/build -Wl,-rpath-link,'$ORIGIN/../../build'"
)

或者:

# 设置第三方库路径
set(3RDPARTY_DIR "${PARENT_DIR}/third_party")

# 设置rpath
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \
-L${3RDPARTY_DIR}/zlib/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/zlib/lib' \
-L${3RDPARTY_DIR}/szlib/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/szlib/lib' \
-L${3RDPARTY_DIR}/hdf5/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/hdf5/lib' \
-L${3RDPARTY_DIR}/x264/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/x264/lib' \
-L${3RDPARTY_DIR}/x265/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/x265/lib' \
-L${3RDPARTY_DIR}/ffmpeg/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/ffmpeg/lib' \
-L${3RDPARTY_DIR}/sigmastar/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/sigmastar/lib' \
-L${3RDPARTY_DIR}/arm_opencv/lib -Wl,-rpath-link,'$ORIGIN/../../third_party/arm_opencv/lib' \
-L${PARENT_DIR}/build -lsigmastar_vVehicle_det -Wl,-rpath-link,'$ORIGIN/../../build'")

编译之后,查看二进制的 rpath

yoyo@yoyo:~/share/driver/dla_detect$ readelf -d test/build/dla_detect
...
0x0000000f (RPATH)                      Library rpath: [/home/yoyo/share/driver/dla_detect/third_party/arm_opencv/share/opencv4/../../lib]
...

查看 rpath

objdump -x path/to/executable | grep RPATH
readelf -d path/to/executable | head -20
chrpath -l path/to/executable

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2300689.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#中File.Copy方法的参数overwrite取false和true的区别

当调用 System.IO.File.Copy 方法时&#xff0c;第三个参数 overwrite 控制着如果目标位置已经存在同名文件的情况下如何处理。 1、当 overwrite 设置为 true 在这种情况下&#xff0c;即使目标路径下已经有相同名称的文件&#xff0c;该方法也会无条件地覆盖现有的文件。这不…

用promptfoo做大模型安全性测评

1. 引入 promptfoo 是一款专为大模型安全测试打造的强大工具。它能通过红队测试、渗透测试以及漏洞扫描等方式&#xff0c;对各类大模型展开深度安全评估&#xff0c;全面检测模型在不同场景下的安全性。 2. 运行promptfoo的过程 安装nodejs 用npm安装promptfoo npm insta…

用STC-ISP写延时函数

若想写出自己可以定义时长的延时函数&#xff0c;需要重新生成一个1ms的延时函数并稍加修改。 STC-ISP生成的1ms的延时函数代码如下&#xff1a; void Delay1ms(void) //12.000MHz {unsigned char data i, j;i 2;j 239;do{while (--j);} while (--i); }将上述代码改为可自定…

Jetson Agx Orin平台JP6.0-r36.3版本修复了vi模式下的原始图像损坏(线条伪影)

1.问题描述 这是JP-6.0 GA/ l4t-r36.3.0的一个已知问题 通过vi模式捕获的图像会导致异常线条 参考下面的快照来演示这些线伪影 这个问题只能通过VI模式进行修复,不应该通过LibArgus看到。 此外,这是由于内存问题。 由于upstream已经将属性名称更改为“dma-noncoherent”…

MSI微星电脑冲锋坦克Pro Vector GP76 12UGS(MS-17K4)原厂Win11系统恢复镜像,含还原功能,预装OEM系统下载

适用机型&#xff1a;【MS-17K4】 链接&#xff1a;https://pan.baidu.com/s/1P8ZgXc6S_J9DI8RToRd0dQ?pwdqrf1 提取码&#xff1a;qrf1 微星笔记本原装出厂WINDOWS11系统自带所有驱动、出厂主题壁纸、系统属性专属联机支持标志、Office办公软件、MSI Center控制中心等预装…

Pycharm中断点使用技巧

1. 打开项目并准备代码 首先&#xff0c;打开 PyCharm 并加载你的 Python 项目&#xff0c;确保你已经有想要调试的 Python 代码文件。如&#xff1a; def add_numbers(a, b):result a breturn resultnum1 5 num2 3 sum_result add_numbers(num1, num2) print(f"Th…

洛谷P11042 [蓝桥杯 2024 省 Java B] 类斐波那契循环数

像是这种填空题的话&#xff0c;就直接暴力还更加省时间&#xff0c;在本地算完后直接提交答案即可 #include<bits/stdc.h> using namespace std;const int N 10000000;bool isnumber(int n) {vector<int> a;int m n;while (n > 0) {a.push_back(n % 10);n / …

echarts心电图封装方法

效果图 代码 <div id"line1" style"width: 100%;height: 100px;"></div>// 生成图标方法 /*** 生成图表* param {array} cData 图表数据* param {string} home 图表渲染位置Id* param {number} speed 刷新速度 值越大&#xff0c;刷新速度越快…

使用Linux创作第一个小程序--进度条

Linux第一个小程序 - 进度条 储备知识 1.回车换行 回车概念 \r 换行概念 \n 2.缓冲区 sleep 先执行1 后执行2&#xff08;c语言中是按顺序执行的&#xff09; 那么在我sleep期间&#xff0c;“Hello World”一定是被保存起来了&#xff08;缓冲区&#xff09;。 缓冲区&a…

初识LLMs

目录 一、Language AI 历史 二、Language AI如何处理text 三、技术一&#xff1a;Bag-of-Words模型 缺点 四、技术二&#xff1a;word2vec&#xff08;稠密向量 / 嵌入向量&#xff09; 缺点 五、嵌入的多种形式 六、技术三&#xff1a;注意力机制 6.1 上下文嵌入 缺…

SpringAI系列 - RAG篇(三) - ETL

目录 一、引言二、组件说明三、集成示例一、引言 接下来我们介绍ETL框架,该框架对应我们之前提到的阶段1:ETL,主要负责知识的提取和管理。ETL 框架是检索增强生成(RAG)数据处理的核心,其将原始数据源转换为结构化向量并进行存储,确保数据以最佳格式供 AI 模型检索。 …

leetcode:942. 增减字符串匹配(python3解法)

难度&#xff1a;简单 由范围 [0,n] 内所有整数组成的 n 1 个整数的排列序列可以表示为长度为 n 的字符串 s &#xff0c;其中: 如果 perm[i] < perm[i 1] &#xff0c;那么 s[i] I 如果 perm[i] > perm[i 1] &#xff0c;那么 s[i] D 给定一个字符串 s &#xff0…

【智驭未来】使用Deepseek进行业务系统集成场景分析

DeepSeek已经出来了一段时间&#xff0c;各系统厂商纷纷加入对他的支持行列&#xff0c;有使用他来进行数据智能预测分析的&#xff0c;有使用他来进行系统知识智能问答的&#xff0c;有进行多语言处理和文档智能解析的&#xff0c;也有开发工具支持AI代码生成的。根据厂商产品…

探秘Transformer系列之(3)---数据处理

探秘Transformer系列之&#xff08;3&#xff09;—数据处理 接下来三篇偏重于工程&#xff0c;内容略少&#xff0c;大家可以当作甜点 _。 0x00 概要 有研究人员认为&#xff0c;大模型的认知框架看起来十分接近卡尔弗里斯顿(Karl Friston)描绘的贝叶斯大脑。基于贝叶斯概率…

cesium视频投影

先看效果 使用cesium做视频投影效果&#xff0c;而且还要跟随无人机移动而移动&#xff0c;我现在用定时器更新无人机的坐标来实现效果具体代码如下&#xff1a; 1、CesiumVideo3d.js(某个cesium技术群大佬分享的) // import ECEF from "./CoordinateTranslate"; le…

[算法学习笔记]1. 枚举与暴力

一、枚举算法 定义 枚举是基于已有知识来猜测答案的问题求解策略。即在已知可能答案的范围内&#xff0c;通过逐一尝试寻找符合条件的解。 2. 核心思想 穷举验证&#xff1a;对可能答案集合中的每一个元素进行尝试终止条件&#xff1a;找到满足条件的解&#xff0c;或遍历完…

Burp Suite基本使用(web安全)

工具介绍 在网络安全的领域&#xff0c;你是否听说过抓包&#xff0c;挖掘漏洞等一系列的词汇&#xff0c;这篇文章将带你了解漏洞挖掘的热门工具——Burp Suite的使用。 Burp Suite是一款由PortSwigger Web Security公司开发的集成化Web应用安全检测工具&#xff0c;它主要用于…

RabbitMQ 3.12.2:单节点与集群部署实战指南

前言&#xff1a;在当今的分布式系统架构中&#xff0c;消息队列已经成为不可或缺的组件之一。它不仅能够实现服务之间的解耦&#xff0c;还能有效提升系统的可扩展性和可靠性。RabbitMQ 作为一款功能强大且广泛使用的开源消息中间件&#xff0c;凭借其高可用性、灵活的路由策略…

【故障处理】- 11G expdp导出缓慢 + Streams AQ: enqueue blocked on low memory等待事件

【故障处理】- 11G expdp导出缓慢 Streams AQ: enqueue blocked on low memory等待事件 一、概述二、故障原因三、解决方法 一、概述 该问题的数据库版本是11.2.0.4&#xff0c;执行expdp导出的时候&#xff0c;小表导出非常缓慢&#xff0c;同时有Streams AQ: enqueue blocke…

《仙台有树》里的馅料(序)

《仙台有树》一起追剧吧&#xff08;二&#xff09;&#xff1a;馅料合集概览 ●德爱武美玩&#xff0c;全面发展 ●猜猜我是谁&真假美清歌 ●失忆的风还是吹到了仙台 ●霸道师徒强制收&你拜我&#xff0c;我拜你&#xff0c;师徒徒师甜蜜蜜 ●霸道总裁强制爱 ●仙台有…