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

一、参考资料

链接选项 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Golang学习笔记_34——组合模式

Golang学习笔记_31——原型模式 Golang学习笔记_32——适配器模式 Golang学习笔记_33——桥接模式 文章目录 一、核心概念1. 定义2. 解决的问题3. 核心角色4. 类图 二、特点分析三、适用场景1. 文件系统2. 图形界面3. 组织架构 四、代码示例&#xff08;Go语言&#xff09;五、…

vue+elementplus创建初始化安装

项目创建初始化 D:\Tool\mysql\education_vue 这个路径下cmd 或打开vscode&#xff0c;把项目丢进code中打开 安装element plus Container 布局容器 | Element Plus npm install element-plus --save 把项目初始文件Homeview AboutView删了&#xff0c;Router index.js中删一…

SQL 优化工具使用之 explain 详解

一、导读 对于大部分开发人员来说&#xff0c;平常接触的无非就是增删改查这些基本操作&#xff0c;创建存储过程&#xff0c;视图等等都是 DBA 该干的活&#xff0c;但是想要把这些基本操作写的近乎完美也是一件难事。 而 explain 显示了 MySQL 如何使用索引来处理 select 语…

仿 Sora 之形,借物理模拟之技绘视频之彩

来自麻省理工学院、斯坦福大学、哥伦比亚大学以及康奈尔大学的研究人员携手开源了一款创新的3D交互视频模型——PhysDreamer&#xff08;以下简称“PD”&#xff09;。PD与OpenAI旗下的Sora相似&#xff0c;能够借助物理模拟技术来生成视频&#xff0c;这意味着PD所生成的视频蕴…

Python的顺序结构和循环结构

文章目录 一、条件语句&#xff08;1&#xff09;条件语句的定义&#xff08;2&#xff09;条件语句的语法&#xff08;a&#xff09;单分支 if&#xff08;b&#xff09;双分支 if-else&#xff08;c&#xff09;多分支 if-elif-elif-...-else &#xff08;3&#xff09;注意事…

04 redis数据类型

文章目录 redis数据类型string类型hash类型list类型set类型zset类型 &#xff08;sortedset&#xff09;通用命令 redis数据类型 官方命令&#xff1a;&#xff1a;http://www.redis.cn/commands.html Redis 中存储数据是通过 key-value 格式存储数据的&#xff0c;其中 val…

AutoGen:玩转多智能体团队协作 (Teams)

&#x1f449;&#x1f449;&#x1f449;本人承接各类AI相关应用开发项目(包括但不限于大模型微调、RAG、AI智能体、NLP、机器学习算法、运筹优化算法、数据分析EDA等) !!!&#x1f449;&#x1f449;&#x1f449; 有意愿请私信!!! AutoGen 的 AgentChat 模块为我们提供了强大…

Python PyCharm DeepSeek接入

Python PyCharm DeepSeek接入 创建API key 首先进入DeepSeek官网&#xff0c;https://www.deepseek.com/ 点击左侧“API Keys”&#xff0c;创建API key&#xff0c;输出名称为“AI” 点击“创建"&#xff0c;将API key保存&#xff0c;复制在其它地方。 在PyCharm中下…

分享8款AI生成PPT的工具!含测评

随着人工智能技术的飞速进步&#xff0c;制作PPT变得愈发便捷&#xff0c;仅需输入主题指令&#xff0c;便能在瞬间获得一份完整的演示文稿。尤其在制作篇幅较长的PPT时&#xff0c;手动编写每一页内容并设计格式和排版&#xff0c;不仅效率低下&#xff0c;而且耗时耗力。 本…

50页PDF|数字化转型成熟度模型与评估(附下载)

一、前言 这份报告依据GBT 43439-2023标准&#xff0c;详细介绍了数字化转型的成熟度模型和评估方法。报告将成熟度分为五个等级&#xff0c;从一级的基础转型意识&#xff0c;到五级的基于数据的生态价值构建与创新&#xff0c;涵盖了组织、技术、数据、资源、数字化运营等多…

aistdio部署deepseek-r1纯教程

前言 笔者电脑未扩容&#xff0c;想玩玩本地化的deepseek&#xff0c;苦于&#x1f447;久矣&#xff0c; 想到之前老师介绍的百度云平台飞桨AI Studio星河社区-人工智能学习与实训社区 于是就开始尝试部署终端版deepseek. 一、新建项目 1.打开飞桨网站&#xff0c;创建not…

实现动态翻转时钟效果的 HTML、CSS 和 JavaScript,附源码

实现动态翻转时钟效果的 HTML、CSS 和 JavaScript 在现代网页设计中&#xff0c;动画效果可以极大地增强用户体验。本文将介绍如何利用 HTML、CSS 和 JavaScript 创建一个动态翻转时钟的效果&#xff0c;模拟经典机械翻页时钟的视觉效果。我们将通过详细的步骤讲解如何实现时钟…

RagFlow+Ollama 构建RAG私有化知识库

RagFlowOllama 构建RAG私有化知识库 关于RAG一、什么是RAGFlow一、RAGFlow 安装配置测服已有服务&#xff1a; mysql、redis、elasticsearch 二、RAGFlow 配置 ollama&#xff1a;本地运行大型语言模型的工具软件。用户可以轻松下载、运行和管理各种开源 LLM。降低使用门槛&…

JavaScript(JS)

介绍 JavaScript(简称:JS)是一门跨平台、面向对象的脚本语言。是用来控制网页行为的&#xff0c;它能使网页可交互 JavaScript 和Java 是完全不同的语言&#xff0c;不论是概念还是设计。但是基础语法类似 JS引入方式 内部脚本:将JS代码定义在HTML页面中 JavaScript代码…

LLM 架构

LLM 分类 : 自编码模型 (encoder) : 代表模型 : BERT自回归模型 (decoder) : 代表模型 : GPT序列到序列模型 (encoder-decoder) : 代表模型 : T5 自编码模型 (AutoEncoder model , AE) 代表模型 : BERT (Bidirectional Encoder Representation from Transformers)特点 : Enc…

剑指 Offer II 023. 两个链表的第一个重合节点

comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20023.%20%E4%B8%A4%E4%B8%AA%E9%93%BE%E8%A1%A8%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E9%87%8D%E5%90%88%E8%8A%82%E7%82%B9/README.md 剑指 Offer II 023. 两…

【git-hub项目:YOLOs-CPP】本地实现04:项目简化

项目跑通之后,我们常常还需要对我们没有用到的任何内容进行删除,以简化项目体积,也便于我们阅读和后续部署。如何实现呢?本篇博客教会大家实现! 项目一键下载【⬇️⬇️⬇️】: 精简后:【GitHub跑通项目:YOLOs-CPP】+【计算机视觉】+【YOLOv11模型】+【windows+Cpp+ONN…

R语言用逻辑回归贝叶斯层次对本垒打数据与心脏移植数据后验预测检验模拟推断及先验影响分析|附数据代码...

全文链接&#xff1a;https://tecdat.cn/?p40152 在统计学领域中&#xff0c;层次建模是一种极为强大且实用的工具。它能够巧妙地处理复杂的数据结构&#xff0c;通过分层的方式对数据进行建模。在贝叶斯统计的框架内&#xff0c;层次建模优势尽显&#xff0c;其可以有效地融合…

解锁机器学习核心算法 | 随机森林算法:机器学习的超强武器

一、引言 在机器学习的广阔领域中&#xff0c;算法的选择犹如为一场冒险挑选趁手的武器&#xff0c;至关重要。面对海量的数据和复杂的任务&#xff0c;合适的算法能够化繁为简&#xff0c;精准地挖掘出数据背后隐藏的模式与价值。机器学习领域有十大核心算法&#xff0c;而随…

网络工程师 (43)IP数据报

前言 IP数据报是互联网传输控制协议&#xff08;Internet Protocol&#xff0c;IP&#xff09;的数据报格式&#xff0c;由首部和数据两部分组成。 一、首部 IP数据报的首部是控制部分&#xff0c;包含了数据报传输和处理所需的各种信息。首部可以分为固定部分和可变部分。 固定…