通俗理解-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.cbin/applib/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_detectPROPERTIESLINK_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_detectPROPERTIESLINK_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.mzph.cn/diannao/70230.shtml

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

相关文章

SpringMVC环境搭建

文章目录 1.模块创建1.创建一个webapp的maven项目2.目录结构 2.代码1.HomeController.java2.home.jsp3.applicationContext.xml Spring配置文件4.spring-mvc.xml SpringMVC配置文件5.web.xml 配置中央控制器以及Spring和SpringMVC配置文件的路径6.index.jsp 3.配置Tomcat1.配置…

window中git bash使用conda命令

window系统的终端cmd和linux不一样&#xff0c;运行不了.sh文件&#xff0c;为了在window中模仿linux&#xff0c;可以使用gui bash模拟linux的终端。为了在gui bash中使用python环境&#xff0c;由于python环境是在anaconda中创建的&#xff0c;所以需要在gui bash使用conda命…

在线考试系统(代码+数据库+LW)

摘 要 使用旧方法对在线考试系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在在线考试系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的在线考试…

c/c++蓝桥杯经典编程题100道(19)汉诺塔问题

汉诺塔问题 ->返回c/c蓝桥杯经典编程题100道-目录 目录 汉诺塔问题 一、题型解释 二、例题问题描述 三、C语言实现 解法1&#xff1a;递归法&#xff08;难度★&#xff09; 解法2&#xff1a;迭代法&#xff08;难度★★★&#xff09; 四、C实现 解法1&#xff1…

赶AI大潮:在VSCode中使用DeepSeek及近百种模型的极简方法

1 赶AI大潮&#xff1a;在VSCode中使用DeepSeek及近百种模型的极简方法 1.1 背景 DeepSeek在春节期间突然大行其道&#xff0c;欣喜国力大增的同时&#xff0c;对于普通IT工作者&#xff0c;如何才能享受这一波AI红利&#xff0c;让自己的工作更出彩呢&#xff1f;   很多人…

【一文读懂】HTTP与Websocket协议

HTTP协议 概述 HTTP (Hypertext Transfer Protocol)&#xff0c;即超文本传输协议&#xff0c;是一种用于在客户端和服务器之间传输超文本&#xff08;例如网页、图片、音频、视频等&#xff09;的通信协议。它是万维网&#xff08;WWW&#xff09;的基础&#xff0c;负责在浏…

IDEA集成DeepSeek

引言 随着数据量的爆炸式增长&#xff0c;传统搜索技术已无法满足用户对精准、高效搜索的需求。 DeepSeek作为新一代智能搜索技术&#xff0c;凭借其强大的语义理解与深度学习能力&#xff0c;正在改变搜索领域的游戏规则。 对于 Java 开发者而言&#xff0c;将 DeepSeek 集成…

从零开始部署DeepSeek:基于Ollama+Flask的本地化AI对话系统

从零开始部署DeepSeek&#xff1a;基于OllamaFlask的本地化AI对话系统 一、部署背景与工具选型 在AI大模型遍地开花的2025年&#xff0c;DeepSeek R1凭借其出色的推理能力和开源特性成为开发者首选。本文将以零基础视角&#xff0c;通过以下工具链实现本地化部署&#xff1a; …

图论入门算法:拓扑排序(C++)

上文中我们了解了图的遍历(DFS/BFS), 本节我们来学习拓扑排序. 在图论中, 拓扑排序(Topological Sorting)是对一个有向无环图(Directed Acyclic Graph, DAG)的所有顶点进行排序的一种算法, 使得如果存在一条从顶点 u 到顶点 v 的有向边 (u, v) , 那么在排序后的序列中, u 一定…

第1章大型互联网公司的基础架构——1.2 客户端连接机房的技术1:DNS

客户端启动时要做的第一件事情就是通过互联网与机房建立连接&#xff0c;然后用户才可以在客户端与后台服务器进行网络通信。目前在计算机网络中应用较为广泛的网络通信协议是TCP/IP&#xff0c;它的通信基础是IP地址&#xff0c;因为IP地址有如下两个主要功能。 标识设备&…

全面解析鸿蒙(HarmonyOS)开发:从入门到实战,构建万物互联新时代

文章目录 引言 一、鸿蒙操作系统概述二、鸿蒙开发环境搭建三、鸿蒙核心开发技术1. **ArkUI框架**2. **分布式能力开发**3. **原子化服务与元服务** 四、实战案例&#xff1a;构建分布式音乐播放器五、鸿蒙开发工具与调试技巧六、鸿蒙生态与未来展望结语 引言 随着万物互联时代…

Android:播放Rtsp视频流的两种方式

一.SurfaceView Mediaplayer XML中添加SurfaceView: <SurfaceViewandroid:id"id/surface_view"android:layout_width"match_parent"android:layout_height"match_parent"/> Activity代码&#xff1a; package com.android.rtsp;impor…

Next.js【详解】CSS 样式方案

全局样式 Global CSS 默认已创建&#xff0c;即 src\app\globals.css&#xff0c;可根据需要修改 默认在全局布局中导入 src\app\layout.tsx import "./globals.css";组件样式 CSS Modules 新建文件 src\app\test\styles.module.css .red {color: red;}导入目标页面…

LVS相关原理

一、LVS集群的体系结构 1.1 LVS简介 LVS 是 Linux Virtual Server 的简称&#xff0c;也就是 Linux 虚拟服务器 , 是一个由章文嵩博士发起的自由软件项目&#xff0c;它的官方站点是 www.linuxvirtualserver.org 。现在 LVS 已经是 Linux标准内核的一部分&#xff0c;在Linux2…

【2025深度学习系列专栏大纲:深入探索与实践深度学习】

第一部分:深度学习基础篇 第1章:深度学习概览 1.1 深度学习的历史背景与发展轨迹 1.2 深度学习与机器学习、传统人工智能的区别与联系 1.3 深度学习的核心组件与概念解析 神经网络基础 激活函数的作用与类型 损失函数与优化算法的选择 1.4 深度学习框架简介与选择建议 第2…

Java与C语言中取模运算符%的区别对比

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: Java 文章目录 &#x1f4af;前言&#x1f4af;C语言中的取模运算符 %基本行为示例 注意事项示例&#xff1a;负数取模 &#x1f4af;Java中的取模运算符 %基本行为示例 对浮点数的支持示例&#xff1a;浮点数取模 符…

OpenCV机器学习(4)k-近邻算法(k-Nearest Neighbors, KNN)cv::ml::KNearest类

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::ml::KNearest 是 OpenCV 机器学习模块中的一部分&#xff0c;它提供了实现 k-近邻算法&#xff08;k-Nearest Neighbors, KNN&#xff09;的…

过于依赖chatgpt编程会有哪些弊端?

过于依赖ChatGPT编程可能会带来以下问题&#xff1a; 1. 基础不扎实&#xff0c;容易“变菜” 以前遇到代码还会琢磨哪里不懂、怎么改&#xff0c;现在直接复制粘贴&#xff0c;时间长了可能连基本的语法和逻辑都搞不清楚。就像考试总抄答案&#xff0c;真让你自己写的时候脑子…

红队视角出发的k8s敏感信息收集——Kubernetes API 扩展与未授权访问

针对 Kubernetes 第三方组件与 Operator 的详细攻击视角分析&#xff0c;涵盖 Service Mesh、Helm Releases 和 Database Operators 的潜在风险及利用方法。 攻击链示例 1. 攻击者通过未授权的 Tiller 服务部署恶意 Helm Chart → 2. 创建后门 Pod 并横向移动至 Istio 控制平…

3D与2D机器视觉机械臂引导的区别

3D与2D机器视觉在机械臂引导中的主要区别如下&#xff1a; 数据维度 2D视觉&#xff1a;仅处理平面图像&#xff0c;提供X、Y坐标信息&#xff0c;无法获取深度&#xff08;Z轴&#xff09;数据。 3D视觉&#xff1a;处理三维空间数据&#xff0c;提供X、Y、Z坐标及物体的姿态…