前段时间,遇到一个开发的业务需求,即在linux下编译生成可执行文件之后或者修改动态库的链接指向,需要修改其相关的链接库的路径并指定到自定义的目录下。若把相关库拷贝到我们指定应用的目录下,而又没有在编译时执行库的路径,通常默认是指定在系统库/lib目录下。因此,需要修改并指定的rpatch.
rpath 参数是指定库运行时首先加载系统依赖库的路径,如果找不到依赖库将到系统默认的路径库查找。
readelf命令,一般用于查看ELF格式的文件信息,常见的文件如在Linux上的可执行文件,动态库(.so)或者静态库(.a) 等包含ELF格式的文件。
- readelf -d test #test为可执行文件
- readelf -d libc.so.6 #libc.so.6为动态库
ldd命令用于打印程序或者库文件所依赖的共享库列表。
- ldd test #test为可执行程序
- ldd libc.so.6 #libc.so.6为动态库
此方式可能更适用于关联库较少的情况之下。
sudo apt install chrpath
- #显示rpath路径,比如
- chrpath -l xxx.so 或者 chrpath -l test
-
- #修改rpath路径,比如
- chrpath -r ./lib xxx.so #其中./lib是需要修改的路径,xxx.so为源路径库
- chrpath -r ./lib test #其中./lib是需要修改的路径,test可执行文件
此方式可能更适用于关联库较少的情况之下。
sudo apt install patchelf
patchelf --set-rpath ./lib xxx.so #其中./lib是需要修改的路径,xxx.so为源路径库
测试例程如下:(libc.so.6是复制/lib下到当前路径下)
比如test这个可执行程序用到的关联库如下:(修改之前)。
发现libc.so.6这个动态库指向=>/lib/x86_64-linux-gnu/libc.so.6 (0x00007efc90075000)
rpath的设置情况,没有设置有这个参数。(修改之前)
patchelf --set-rpath ./ test #修改可执行程序test的rpatch为当前的路径下
此时查看libc.so.6的依赖库路径变为./libc.so.6
查看test的文件信息如下这一行:
0x000000000000001d (RUNPATH) Library runpath: [./]
说明设置成功!
查看更多编译知识:
makefile模板以及多层Makefile编译(附源码)
GCC详解的-Wl选项说明与测试
gcc -o test test.c -I. -L. -lc -Wl,-rpath=.
其中
-I. 是指定头文件路径为当前目录下;
-L. 是指定库文件路径为当前目录下;
-lc 是从-L指定库文件路径下去找libc.so.6这个库,也就是库名砍头去尾(类似使用过-lpthread);
-Wl,-rpath=. 为告诉编译器将后面的参数传递给链接器。
此时查看libc.so.6的依赖库路径变为./libc.so.6
查看test的文件信息如下这一行:
0x000000000000001d (RUNPATH) Library runpath: [.]
- IF(UNIX)
- set(CMAKE_SKIP_BUILD_RPATH TRUE)
- set(CMAKE_CXX_FLAGS "-Wl,-z,origin,-rpath,$ORIGIN")
- ENDIF()
或者
- set(CMAKE_SKIP_BUILD_RPATH FALSE) # 编译时加上RPATH
- set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # 编译时RPATH不使用安装的RPATH
- set(CMAKE_INSTALL_RPATH "./") # 安装RPATH为当前目录
- set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) # 安装的执行文件不加上RPATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yimning/lib
冒号:为设置多个路径下的分割符号。设置之后再去编译即可。
参考链接:
https://blog.csdn.net/sinat_35178307/article/details/109165060
https://blog.csdn.net/sinat_35178307/article/details/109164966