当前位置:网站首页>CMake中INSTALL_RPATH与BUILD_RPATH问题
CMake中INSTALL_RPATH与BUILD_RPATH问题
2022-08-09 06:23:00 【喜欢打篮球的普通人】
1.RPATH和RUNPATH区别
RPATH和RUNPATH都可以用来在运行时搜索动态库。
- 下面用一个简单的例子说明二者的区别。
- eg:一个小工程中,有1个头文件和3个源文件。
头文件sub.h中的内容如下:
#ifndef TESTRPATH_SUB_H
#define TESTRPATH_SUB_H
void f1(void);
void f2(void);
#endif
源文件a.c中的内容如下:
#include "sub.h"
void f1(void)
{
}
源文件b.c中的内容如下:
#include "sub.h"
void f2(void)
{
f1();
}
源文件main.c中的内容如下:
#include "sub.h"
int main(void)
{
f2();
}
测试:
- 在Ubuntu16.04 + gcc5.4中编译,命令及结果如下:
[email protected]:~/TestRpath$ gcc a.c -fPIC -shared -o liba.so
[email protected]:~/TestRpath$ gcc b.c -fPIC -shared -L$PWD -la -o libb.so
[email protected]:~/TestRpath$ gcc main.c -L$PWD -Wl,-rpath,$PWD -lb
[email protected]:~/TestRpath$ ldd a.out
linux-vdso.so.1 => (0x00007ffe00568000)
libb.so => /home/madengyun/TestRpath/libb.so (0x00007f8baa94c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8baa582000)
liba.so => /home/madengyun/TestRpath/liba.so (0x00007f8baa380000)
- 在Ubuntu18.10 + gcc5.4中编译,命令及结果如下:
[email protected]:~/TestRpath$ gcc a.c -fPIC -shared -o liba.so
[email protected]:~/TestRpath$ gcc b.c -fPIC -shared -L$PWD -la -o libb.so
[email protected]:~/TestRpath$ gcc main.c -L$PWD -Wl,-rpath,$PWD -lb
[email protected]:~/TestRpath$ ldd a.out
linux-vdso.so.1 (0x00007fff635a1000)
libb.so => /home/mdy/TestRpath/libb.so (0x00007f59d326f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f59d2e7e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f59d3673000)
liba.so => not found
在Ubuntu18.10中编译生成的app,ldd显示找不到liba.so。
- 但其实liba.so和libb.so在同一目录下,ldd可以找到libb.so,却找不到liba.so。
用readelf -d分析两种环境下生成的app,
- 可以看出Ubuntu16.10中生成的是RPATH,而Ubuntu18.10中生成的是RUNPATH。
解释:
- 简单地说,在搜索app的间接依赖库时,RPATH起作用,但RUNPATH不起作用。
- 在使用RUNPATH的情况下,很可能还要再配合LD_LIBRARY_PATH一块使用。
所以:最好使用RPATH,这样就不用依赖LD_LIBRARY_PATH了
如何控制生成RPATH还是RUNPATH?
- 链接时使用–enable-new-dtags可以固定生成RUNPATH,使用–disable-new-dtags可以固定生成RPATH。
set_target_properties(XXX LINK_FLAGS "-Wl,--disable-new-dtags")
所以,下面仅对CMake的RPATH进行讨论
2.CMake build之后消除RPATH
Make对于RPATH的管理也非常人性化。
- 官方说法是当动态库的编译也和执行档在同级目录下的时候,CMake会自动给执行档加入适当的RPATH
- 具体可以通过readelf -d executable来查看相关的RPATH路径(target_add_library就会增加RPATH到TARGET上)。
所以有的时候用QMake编译之后还得手动加一把LD_LIBRARY_PATH,而用CMake编译之后,直接执行执行档就可以了。 - 所以CMake搜索库的顺序如下:
搜索.so的优先级顺序
RPATH: 写在elf文件中
LD_LIBRARY_PATH: 环境变量
RUNPATH: 写在elf文件中
ldconfig的缓存: 配置/etc/ld.conf*可改变
默认的/lib, /usr/lib
CMake在默认情况下是会给你的exe加入相关RPATH的,这个时候可能会有不想要相关RPATH的需求,仔细查阅寻找之后发现,CMake里面维护了3个比较重要的RPATH变量,即:
- CMAKE_SKIP_RPATH
- CMAKE_SKIP_BUILD_RPATH
- CMKAE_INSTALL_RPATH.
构建期间和安装期间不允许CMake给你加入相关RPATH;
想要追加RPATH,只需要对这三个变量设置成FALSE
cmake -B build -DCMAKE_SKIP_RPATH=TRUE
cmake .. -DCMAKE_SKIP_BUILD_RPATH=TRUE
cmake .. -DCMAKE_SKIP_INSTALL_RPATH=TRUE
3.CMake install之后保持RPATH
如果你没有显示指定
- CMAKE_SKIP_RPATH,
- CMAKE_BUILD_WITH_INSTALL_RPATH,
- CMAKE_SKIP_BUILD_RAPTH,
- CMAKE_SKIP_INSTALL_RPATH
默认CMake在帮你编译之后,如果你使用了相关动态库,它会在相应的exec文件中增加你相关生成动态库的路径,这样当你每次去执行的时候你不需要每次都LD_LIBRARY_PATH就可以正常运行。
可以看到,当前myexe中的RPATH字段有一个Library rpath,其中指定了你生成相应动态库target的目标路径
readelf -d myexe
或者
来查看当前executable已经寻找到了哪些动态库。
ldd -r myexe
- 因为目前的RPATH都是写的绝对路径
所以移动相关shared_lib库的路径,这个时候你再去运行myexe,你就会发现它已经找不到相关的动态库了。
make install下CMake是如何处理RPATH的?
- CMake为了方便用户的安装,默认在make install之后会自动remove删除掉相关的RPATH,这个时候你再去查看exe的RPATH,已经发现没有这个字段了。
- 因此,当每次make install之后,我们进入到安装路径下执行相关exe的时候,就会发现此时的exe已经找不到相关的库路径了,因为它的RPATH已经被CMake给去除了。
如何让CMake能够在install的过程中写入相关RPATH,并且该RPATH不能使当初build的时候的RPATH呢?
- 答案就是CMAKE_INSTALL_RPATH这个全局变量和INSTALL_RPATH这个target属性。
CMake在安装的过程会有一个和configure一样的安装路径,CMAKE_INSTALL_PREFIX(configure下是–prefix,当然也可以用shell下的全局变量DESTDIR);
这个时候它会把你的安装文件安装到你prefix下的相对路径下,因此当我们希望在make install的时候,比如当前的share_lib在lib目录下,我们希望安装之后的RPATH可以自动找到它,我们就可以这么写
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
需要注意的是,这个变量是全局变量,意味着你所有的target的RPATH都会在install的时候被写成这个(包括myexe和不需要RPATH的share_lib)
set_target_properties(myexe PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" LINK_FLAGS "-Wl,--disable-new-dtags")
这样就可以保证只针对当前的target进行make install的时候RPATH的写入了。
在gcc中,设置RPATH的办法
设置linker的rpath选项:$ gcc -Wl,-rpath,/your/rpath/ test.cpp
如果需要设置$ORIGIN:$ gcc -Wl,-rpath,‘$ORIGIN/lib’ test.cpp。
RPATH中有个特殊的标识符$ORIGIN。这个标识符代表elf文件自身所在的目录。
当希望使用相对位置寻找.so文件,就需要利用$ORIGIN设置RPATH。多个路径之间使用冒号:隔开。在CMake中,事情则有些不同。
由于CMake需要包揽软件安装的事宜,因此CMake使用两个变量来控制RPATH:INSTALL_RPATH和BUILD_RPATH。
SET_TARGET_PROPERTIES(target
PROPERTIES INSTALL_RPATH "$ORIGIN;/another/run/path")
注意,在CMake中,多个RPATH使用分号隔开,而不是冒号。这是估计是因为冒号在CMake语法中有其他用途。
边栏推荐
- 具有CT造影功能的硫化铋纳米棒|硫化铋-锌原卟啉复合材料(PAMAM/Bi2S3复合纳米粒子)
- redis 运行lua 脚本 出现Invalid argument(s)
- MYSQL Advanced Chapter - Query Interception Analysis, Lock Mechanism, Master-Slave Replication
- uniapp实现防抖搜索
- How to automatically fill down an excel table without dragging the mouse down
- 【R语言】对文件进行归一化整理到各文件类型文件夹
- 文本字符串长度排序 - 在线工具
- [HNOI2002]营业额统计
- 常用Oracle命令
- 年薪35W的测试工程师被裁亲身经验:不得不听的忠告
猜你喜欢
Redis 2 - 高级
Likou Brush Question 180
带头双向循环链表的增删查改(C语言实现)
半胱氨酸/半乳糖/苝二酰亚胺功能化Fe3O4四氧化三铁纳米材料|科研试剂
IQ Products CMV Brite Turbo试剂盒的原理
Excel受保护的工作表怎么操作?
普罗米修斯原理及节点发布
Magnetic Core-Shell Fe3O4 Particles Supported Gold Nanostars | Magnetic Fe3O4-POSS-COOH | Superparamagnetic Fe3O4-Polydopamine Core-Shell Nanoparticles
Bismuth sulfide nanorods with CT imaging function | Bismuth sulfide-zinc protoporphyrin composites (PAMAM/Bi2S3 composite nanoparticles)
- [email protected]@cadmium sulfide nanocore-shell structure material|Fe3O4 magnetic nanop"/>
Superparamagnetic iron [email protected]@cadmium sulfide nanocore-shell structure material|Fe3O4 magnetic nanop
随机推荐
抗菌药物丨Toronto Research Chemicals 天冬酰胺D
Ferric oxide/bismuth sulfide nanocomposites ([email protected]@BSABiS nanoparticles) | dendrimer-stabilized bismuth sulfide nanop
After the VB.net program is closed, the background is still connected to SQL
The 24th day of the special assault version of the sword offer
Regular Expression - Determine if a string matches the "AABB" pattern
普罗米修斯原理及节点发布
金仓数据库能否设置事务自动提交
uniapp实现防抖搜索
Molybdenum disulfide/hafnium dioxide composite nanomaterials (MoS2/HfO2) | tantalum-doped hafnium dioxide nanoparticles (Qi Yue bio)
缓存技术使用
TCP segment of a reassembled PDU
Kubernetes apparmor profile
ZIP压缩包文件删除密码的方法
Deep Learning - Principles of Neural Networks 2
How to find package information and pin definitions for NXP S32K1xx series microcontrollers
Text String Length Sorting - Online Tool
Go lang1.18入门精炼教程——第一章:环境搭建
redis 运行lua 脚本 出现Invalid argument(s)
中英文说明书丨CalBioreagents ACTH N端单克隆抗体
Unity Gobang Game Design and Simple AI (2)