网站qq临时会话不需要添加好友,专业网站开发多少钱,WordPress 短码转换,中国万维网官网域名注册网站目录
1.Linux 动态库相关知识
1.1.动态库查找路径
1.2.查看程序依赖的动态库
1.3.修改动态库查找路径的方法
1.4.动态链接器缓存管理
2.-Wl参数
3.-L选项#xff08;编译时路径#xff09;
4.-rpath参数(运行时路径)
5.-rpath-link 参数
6.常见问题与解决方案
7.总…目录
1.Linux 动态库相关知识
1.1.动态库查找路径
1.2.查看程序依赖的动态库
1.3.修改动态库查找路径的方法
1.4.动态链接器缓存管理
2.-Wl参数
3.-L选项编译时路径
4.-rpath参数(运行时路径)
5.-rpath-link 参数
6.常见问题与解决方案
7.总结 在 Linux 系统中编译和链接动态库时-L、-rpath和-rpath-link是三个非常重要的参数它们分别解决了动态库编译、链接和运行时的不同问题。
1.Linux 动态库相关知识
1.1.动态库查找路径 一个典型的 C/C 程序的构建流程是预处理汇编编译链接。而执行链接的程序其实是 ld通常编译器比如 GCC 都会自动调用 ld 去进行链接用户不必关注其中的细节。而 ld 查找动态库的顺序是 1.程序本身指定的路径, 即是rpath或 runpath指定的目录
RPATH硬编码在 ELF 文件中优先级最高。RUNPATH与 RPATH 类似但优先级低于 LD_LIBRARY_PATH。 2.环境变量 LD_LIBRARY_PATH 指定的目录
用户自定义的临时路径多个路径用冒号 : 分隔。例如export LD_LIBRARY_PATH/path/to/lib:$LD_LIBRARY_PATH。 3.runpath 指定的目录 4./etc/ld.so.cache缓存文件通常包含 /etc/ld.so.conf 文件编译出的二进制比如 CentOS 上该文件会使用 include 从而使用 ld.so.conf.d 目录下面所有的 *.conf 文件这些都会缓存在 ld.so.cache 中
这些文件中指定的路径会被动态链接器缓存通过 ldconfig 命令更新。 5.系统默认路径比如 /lib/usr/lib。
/lib系统核心库如 libc.so。/usr/lib用户级库。/usr/local/lib本地安装的库如自行编译的软件。
在编译时若使用 -z nodefaultlib 选项编译则会跳过 4 和 5。至于 runpath和 rpath 类似都是二进制ELF文件的动态 section 属性分别为 DT_RUNPATH 和 DT_RPATH唯一区别就是是否优先于 LD_LIBRARY_PATH 来查找。 rpath vs. runpathrpath 和 runpath 是嵌入在可执行文件或共享库中的路径列表用于指定运行时查找共享库的位置。rpath 是旧标准runpath 是新标准功能类似但优先级不同。 1.2.查看程序依赖的动态库
1.ldd 命令
ldd /path/to/program # 显示程序依赖的所有动态库及其路径
若某库显示为 not found表示系统未找到该库。
2.readelf 命令
readelf -d /path/to/program | grep -E (RPATH|RUNPATH|NEEDED)
输出示例
0x000000000000000f (RPATH) Library rpath: [/path/to/lib]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
1.3.修改动态库查找路径的方法
1.临时修改通过 LD_LIBRARY_PATH 环境变量
export LD_LIBRARY_PATH/path/to/lib:$LD_LIBRARY_PATH # 当前终端生效
# 或添加到 ~/.bashrc 中使其永久生效
echo export LD_LIBRARY_PATH/path/to/lib:$LD_LIBRARY_PATH ~/.bashrc
source ~/.bashrc
2.永久修改编辑 /etc/ld.so.conf 或添加新配置
# 方法1直接编辑主配置文件
sudo vim /etc/ld.so.conf
# 添加一行/path/to/lib
# 保存后更新缓存
sudo ldconfig# 方法2在 /etc/ld.so.conf.d/ 目录下创建新配置文件
sudo touch /etc/ld.so.conf.d/myapp.conf
sudo echo /path/to/lib /etc/ld.so.conf.d/myapp.conf
sudo ldconfig # 更新缓存
3.编译时指定通过 -Wl,-rpath 选项
在编译程序时使用 -Wl,-rpath 将路径硬编码到程序中
gcc -o myapp myapp.c -L/path/to/lib -lmylib -Wl,-rpath,/path/to/lib
优点无需修改系统配置或环境变量。缺点路径被固定若库位置改变需重新编译。
1.4.动态链接器缓存管理
1.更新缓存
当添加新库或修改 /etc/ld.so.conf 后需执行
sudo ldconfig # 重建动态链接器缓存
2.查看缓存内容
ldconfig -p # 显示当前缓存的所有库及其路径
2.-Wl参数 在 Linux 系统中-Wl 是 GCC 编译器的一个重要参数用于向链接器如 ld传递额外选项。由于 GCC 是编译和链接的前端工具真正处理链接过程的是链接器因此需要通过 -Wl 将参数传递给链接器。 基本语法
gcc [编译选项] -Wl,链接器选项1[,链接器选项2,...] [源文件]
将逗号分隔的选项传递给链接器。如
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
3.-L选项编译时路径
编译时指定链接器搜索库文件的路径。仅影响链接过程不影响程序运行时的库查找。
假设你有一个自定义库 libmath.so 位于 /opt/mylibs 目录下
g main.cpp -L/opt/mylibs -lmath -o myapp
-L/opt/mylibs告诉链接器在 /opt/mylibs 目录下搜索 libmath.so。-lmath链接名为 libmath.so 的库。
-L一般用于链接非标准位置的第三方库如 /usr/local/lib 以外的路径。
4.-rpath参数(运行时路径) 运行时搜索路径将动态库搜索路径硬编码到可执行文件中运行时生效。通过修改可执行文件的 .dynamic 段将路径硬编码到二进制文件中。 -rpath 的作用相当于在程序运行时设置了 LD_LIBRARY_PATH 环境变量因为 -rpath指定的路径会被记录在生成的可执行程序中用于运行时查找需要加载的动态库 。因此在开发板中无需设置环境变量即可找到相关的动态库。通常情况下推荐使用 -Wl,-rpath 选项。
# 单个路径
-L/mylib -lmylib -Wl,-rpathdir# 多个路径
-L/mylib -lmylib -Wl,-rpath,dir1:dir2:...:dirN 示例
g main.cpp -L/opt/mylibs -lmath -Wl,-rpath/opt/mylibs -o myapp
-Wl,-rpath/opt/mylibs将 /opt/mylibs 添加到程序运行时的库搜索路径。
等价写法
# 直接使用链接器参数
g main.cpp -L/opt/mylibs -lmath -Wl,-rpath/opt/mylibs -o myapp# 或使用环境变量
export LDFLAGS-Wl,-rpath/opt/mylibs
g main.cpp -L/opt/mylibs -lmath $LDFLAGS -o myapp
特殊变量
$ORIGIN表示可执行文件所在目录常用于相对路径。
# 搜索与可执行文件同级的 lib 目录
-Wl,-rpath$ORIGIN/../lib
注意在 Makefile 或 shell 脚本中使用时需用双引号防止变量提前展开
-Wl,-rpath\$$ORIGIN/../lib
在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)
5.-rpath-link 参数 用于指定动态库的搜索路径在链接阶段该选项只在链接阶段起作用不会被写入elf文件中。辅助链接器解析库之间的依赖关系但不影响程序运行时的库搜索路径。适用于复杂的库依赖链如 A 依赖 BB 依赖 C。 示例假设
libapp.so 依赖 libmath.so。libmath.so 依赖 libutils.so位于 /opt/thirdparty。
# 链接 libapp.so 时指定 libmath.so 的依赖路径
g -shared -fPIC app.cpp -L/opt/mylibs -lmath -Wl,-rpath-link/opt/thirdparty -o libapp.so
-Wl,-rpath-link/opt/thirdparty告诉链接器libmath.so 依赖的 libutils.so 在 /opt/thirdparty 目录下。但程序运行时仍需通过 -rpath 或环境变量指定 /opt/thirdparty。
在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 的区别
-rpath同时影响链接和运行时的库搜索。-rpath-link仅在链接时生效不修改可执行文件的运行时路径。
三者对比
参数生效阶段是否影响运行时作用-L链接时否指定链接器搜索库的路径-rpath运行时是修改程序运行时的库搜索路径硬编码到二进制文件-rpath-link链接时否辅助链接器解析库依赖关系但不影响程序运行时的搜索路径
6.常见问题与解决方案
1.错误libxxx.so: cannot open shared object file: No such file or directory
可能原因 库未安装。库路径未包含在查找路径中。 解决方案
# 1. 确认库是否存在
find / -name libxxx.so* 2/dev/null# 2. 若存在将路径添加到 LD_LIBRARY_PATH
export LD_LIBRARY_PATH/path/to/lib:$LD_LIBRARY_PATH# 3. 或添加到系统配置
echo /path/to/lib | sudo tee -a /etc/ld.so.conf
sudo ldconfig
2.区分 RPATH 和 RUNPATH
RPATH在 RUNPATH 和 LD_LIBRARY_PATH 之前被搜索。RUNPATH在 LD_LIBRARY_PATH 之后被搜索。
修改方法
# 编译时指定 RPATH
gcc -Wl,-rpath,/path/to/lib ...# 编译时指定 RUNPATH需显式使用 -rpath-link
gcc -Wl,-rpath-link,/path/to/lib -Wl,-rpath,$ORIGIN/../lib ...
$ORIGIN 表示程序所在目录用于相对路径。
3.链接时提示找不到库的依赖
/usr/bin/ld: libmath.so: undefined reference to function_in_libutils
原因
libmath.so 依赖 libutils.so但链接器找不到 libutils.so。
解决方案
# 临时指定依赖路径
g -shared -fPIC app.cpp -L/opt/mylibs -lmath -Wl,-rpath-link/opt/thirdparty -o libapp.so
7.总结
优先使用 -rpath减少对环境变量的依赖提高程序可移植性。使用 $ORIGIN让库路径相对于可执行文件避免硬编码绝对路径。谨慎使用 -rpath-link仅在链接复杂依赖的库时使用避免污染运行时路径。测试部署确保程序在目标环境中能正常找到库如使用 ldd myapp 检查。
通过合理组合 -L、-rpath 和 -rpath-link可以灵活控制动态库的编译、链接和运行时行为解决复杂的依赖问题。