xizhibei / blog

个人博客,(Node.js/Golang/Backend/DevOps),欢迎 Star, Watch 订阅以及评论
https://blog.xizhibei.me
Other
431 stars 29 forks source link

RPATH 简介以及 CMake 中的处理 #161

Open xizhibei opened 3 years ago

xizhibei commented 3 years ago

所谓的 RPATH,就是硬编码在可执行文件或者动态库中的一个或多个路径,被动态链接加载器用来搜索依赖库。1

这个值是存在可执行文件或者动态库的 ELF 结构中的 .dynamic 小节中,它可以用 readelf 或者 objdump 查看。

具体就是 readelf -d a.out | grep RPATH 或者 objdump -x a.out | grep RPATH

Linux 中的动态链接加载器搜索路径

至于搜索路径,除了 RPATH,链接加载器在 Linux 中,还会有另外几个关键的路径,他们的搜索顺序如下:2

至于为何需要那么多的可配置方式,就在于不同的程序会有不同的需求,比如对于不同版本库的需求,就需要单独设置 RPATH,用来指定依赖库的位置,而不是使用系统相关的 LD_LIBRARY_PATH,因为这个环境变量可能会破坏其它程序的运行。

下面来说说 CMake 中的 RPATH。

CMake 中的 RPATH

跟 RPATH 相关的设置有如下几个(MacOS 相关的今天按下不表):

这些设置,可以使用 set_target_properties 单独设置在 target 上,也可以在加上 CMAKE_ 前缀后,设置成全局配置。至于如何使用,完全取决于你想要如何运行你的程序,比如从编译目录中或者安装目录中运行,可能就需要完全不同的配置。

其实在大多数场景下,我们都不需要设置这些东西,因为一旦设置了 RPATH,很可能会不方便移植,但是如果你需要单独的依赖库路径的时候,这些东西就需要了。

而如果你真的需要 RPATH,建议的做法是 使用相对路径,这样就会更容易移植到不同的机器上,比如 Linux 系统中,可以使用 $origin3

set(CMAKE_INSTALL_RPATH "$origin/../lib")

Ref

  1. wikipedia - Rpath
  2. CMake/RPATH-handling
  3. RPATH and $ORIGIN