当前位置:网站首页>INSTALL_RPATH and BUILD_RPATH problem in CMake

INSTALL_RPATH and BUILD_RPATH problem in CMake

2022-08-09 06:27:00 Ordinary people who like to play basketball

1.RPATH和RUNPATH区别

RPATH和RUNPATHBoth can be used to search dynamic libraries at runtime.

  • The following is a simple example to illustrate the difference between the two.
  • eg:in a small project,有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 -dAnalysis of the two environments generatedapp,

  • 可以看出Ubuntu16.10中生成的是RPATH,而Ubuntu18.10中生成的是RUNPATH.
    在这里插入图片描述

解释:

  • 简单地说,在搜索appWhen an indirect dependency library is used,RPATH起作用,但RUNPATH不起作用.
  • 在使用RUNPATH的情况下,Possibly more cooperationLD_LIBRARY_PATH一块使用.

所以:最好使用RPATH,这样就不用依赖LD_LIBRARY_PATH了
How to control generationRPATH还是RUNPATH?

  • 链接时使用–enable-new-dtagsCan be fixedRUNPATH,使用–disable-new-dtagsCan be fixedRPATH.
set_target_properties(XXX  LINK_FLAGS "-Wl,--disable-new-dtags")

所以,下面仅对CMake的RPATH进行讨论

2.CMake buildremove afterRPATH

Make对于RPATHThe management is also very humane.

  • The official statement is when the compilation of the dynamic library is also in the same directory as the executable file,CMakeAppropriate ones will be added to the executable file automaticallyRPATH
  • 具体可以通过readelf -d executable来查看相关的RPATH路径(target_add_library就会增加RPATH到TARGET上).
    所以有的时候用QMakeYou have to add it manually after compilingLD_LIBRARY_PATH,而用CMake编译之后,Just execute the executable directly.
  • 所以CMake搜索库的顺序如下:
搜索.so的优先级顺序
RPATH: 写在elf文件中
LD_LIBRARY_PATH: 环境变量
RUNPATH: 写在elf文件中
ldconfig的缓存: 配置/etc/ld.conf*可改变
默认的/lib, /usr/lib

CMakeIt will be given to you by defaultexe加入相关RPATH的,At this time, there may be undesired correlationsRPATH的需求,Found it after a careful search,CMake里面维护了3个比较重要的RPATH变量,即:

  • CMAKE_SKIP_RPATH
  • CMAKE_SKIP_BUILD_RPATH
  • CMKAE_INSTALL_RPATH.
Not allowed during build and during installationCMakeAdd to youRPATH;
想要追加RPATH,Just set these three variables to FALSE
cmake -B build -DCMAKE_SKIP_RPATH=TRUE
cmake .. -DCMAKE_SKIP_BUILD_RPATH=TRUE
cmake .. -DCMAKE_SKIP_INSTALL_RPATH=TRUE

3.CMake install之后保持RPATH

If you don't explicitly specify

  • CMAKE_SKIP_RPATH,
  • CMAKE_BUILD_WITH_INSTALL_RPATH,
  • CMAKE_SKIP_BUILD_RAPTH,
  • CMAKE_SKIP_INSTALL_RPATH

默认CMakeAfter compiling for you,If you use the relevant dynamic library,它会在相应的execAdd the path of your related dynamic library to the file,This way you don't need to do it every time you go to execute itLD_LIBRARY_PATH就可以正常运行.

可以看到,当前myexe中的RPATH字段有一个Library rpath,Which specifies that you generate the corresponding dynamic librarytarget的目标路径
readelf -d myexe

或者
来查看当前executableWhich dynamic libraries have been found.
ldd -r myexe
  • 因为目前的RPATH都是写的绝对路径
    So mobile relatedshared_lib库的路径,This time you go to runmyexe,You will find that it can no longer find the relevant dynamic library.

make install下CMake是如何处理RPATH的?

  • CMakeIn order to facilitate the installation of users,默认在make install之后会自动removeDelete the relevant onesRPATH,This time you go to checkexe的RPATH,It has been found that this field does not exist.
  • 因此,当每次make install之后,We enter into the installation path to execute the relevantexe的时候,will find out at this timeexeThe relevant library path has not been found,因为它的RPATH已经被CMake给去除了.

如何让CMake能够在installThe process of writing relatedRPATH,并且该RPATHCan't make it at firstbuild的时候的RPATH呢?

  • 答案就是CMAKE_INSTALL_RPATHThis global variable and INSTALL_RPATH这个target属性.
    CMakeThere will be a sum during the installation processconfigure一样的安装路径,CMAKE_INSTALL_PREFIX(configure下是–prefix,当然也可以用shell下的全局变量DESTDIR);
    This time it will install your installation files to youprefixunder the relative path,So when we want to bemake install的时候,比如当前的share_lib在lib目录下,We hope after installationRPATHIt can be found automatically,我们就可以这么写
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)

需要注意的是,这个变量是全局变量,Means all yourstarget的RPATH都会在installwas written as this(包括myexe和不需要RPATH的share_lib)
set_target_properties(myexe PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" LINK_FLAGS "-Wl,--disable-new-dtags")
This is guaranteed to only target the current onetarget进行make install的时候RPATH的写入了.

在gcc中,设置RPATH的办法

  • 设置linker的rpath选项:$ gcc -Wl,-rpath,/your/rpath/ test.cpp

  • 如果需要设置$ORIGIN:$ gcc -Wl,-rpath,‘$ORIGIN/lib’ test.cpp.
    RPATHhas a special identifier in it$ORIGIN.This identifier representselfThe directory where the file itself resides.
    When you want to use relative position seeking.so文件,就需要利用$ORIGIN设置RPATH.多个路径之间使用冒号:隔开.

  • 在CMake中,Things are a little different.
    由于CMakeNeed to take care of software installation,因此CMakeUse two variables to controlRPATH:INSTALL_RPATH和BUILD_RPATH.

SET_TARGET_PROPERTIES(target
    PROPERTIES INSTALL_RPATH "$ORIGIN;/another/run/path")
注意,在CMake中,多个RPATH使用分号隔开,而不是冒号.This is estimated because the colon is thereCMakeGrammar has other uses.
原网站

版权声明
本文为[Ordinary people who like to play basketball]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/221/202208090622384002.html