5

g++中的rpath和runpath

 3 years ago
source link: https://hkvision.cn/2020/11/27/g-%E4%B8%AD%E7%9A%84rpath%E5%92%8Crunpath/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

g++中的rpath和runpath

2020年11月27日

本文为原创文章,转载注明出处,欢迎关注网站https://hkvision.cn

最近在弄Linux上的程序,然后由于涉及到要调用mkl的包(armadillo中用mkl+openblas要快很多),而mkl安装的时候库是不会进入/usr/lib这样的系统路径下的,然后引发了一些问题。

稍微对程序的加载等方面熟悉一点的童鞋会知道,C++分为编译链接和运行两个部分,对于g++这样的编译器来说,需要链接器知道要加载的动态链接库(共享对象)的位置,对于一个二进制文件来说,在运行的时候也需要知道动态链接库的位置,这就涉及到两个链接,一个是编译时链接,一个是运行时链接。

在g++中,这两个链接是由两个参数来控制的,一个是-L,一个是-Wl,-rpath,由于之前弄明白链接的过程之后使用了这两个参数,程序没有出问题。但是这次我发现即使配置了这两个参数仍然有问题,上网查了一下,又深入了一点点。

rpath和runpath

这涉及到另外一个小知识,大家应该知道Linux中的可执行文件是elf格式的文件,这种文件以段来进行区域划分,在可执行文件的elf中,就存在一个section,名字叫做rpath,这里面存储了执行这个文件的时候搜索库的位置,因此在加载可执行文件的时候就会在这个位置搜索库。

本来这一切好好的,但是存在另外一种段,名字叫做runpath,乍一眼看这个应该行使和rpath类似的功能,但是不是的,具体的一些内容大家可以参考这个文章RPATH与RUNPATH - LiuYanYGZ - 博客园 (cnblogs.com),估计是机器翻译的。其实runpath就是一个控制搜索逻辑的一个段,并不是会在这个路径下面搜索(可能我的理解也不太对,毕竟文章写的太抽象了)。

g++的神奇操作

本来我不应该纠结这两个段的区别的,但是,新版本的g++(9.3.0),glibc版本2.31,在指定-Wl,-rpath的时候,默认只会增加上runpath,而没有rpath。这就导致这个参数失效了。于是出现了诡异的一幕,明明指定了运行时链接的路径但是还是提示没有找到库。

罪魁祸首就是一个新的链接器参数,叫做--enable-new-dtags,man手册里面说这个默认关着的,但是实际上我使用的时候发现这玩意是开着的,设置了这个参数就会导致只有runpath而没有rpath,因此如果想要回到原来的状态,就得手动关掉这个参数--disable-new-dtags,这样编译出来的文件就会只有rpath而没有runpath,之后就又能愉快的玩耍了


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK