如何避免在 CMake 安装步骤中删除 RPATH?

2024-01-06

我正在使用 CMake 开发一个 C++ 项目,在其中构建一个可执行文件foo使用共享库libbar(正在通过添加ExternalProject_add).

可执行文件build/src/foo在构建目录中工作得很好。但是,如果我跑make install,安装的可执行文件/bin/foo给我以下错误。

./foo: error while loading shared libraries: libbar.so.11: cannot open shared object file: No such file or directory

我知道我不是唯一一个有这个问题的人(参见例如here https://stackoverflow.com/questions/32469953/why-is-cmake-designed-so-that-it-removes-runtime-path-when-installing),而且我也知道处理rpath通过 CMake,请参阅here https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling。据我了解,install步骤剥离rpath变量,说明找不到库文件。

我通过运行检查了这一点ldd foo在目录中/build/src/导致

libbar.so => /PATH/TO/LIBBAR/libbar.so

当我在目录中运行相同的命令时/build/bin/, I get

libbar.so => not found

现在我的问题。一般来说,如何避免可执行文件在安装过程中“忘记”共享库的位置?我基本上希望安装的可执行文件具有相同的路径rpath正如其中的那个build目录。

到目前为止我已经尝试过的

我读到你可以避免通过以下方式剥离路径

SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

然而,这根本不起作用。我不知道为什么不,因为这是建议的精确解决方案here https://stackoverflow.com/questions/32469953/why-is-cmake-designed-so-that-it-removes-runtime-path-when-installing and 在文档中 https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling.

我当然可以通过手动设置路径

SET(CMAKE_INSTALL_RPATH "$LIBBAR_PATH}/lib")

这确实有效,但是这个解决方案太具体了libbar并例如不起作用,如果我在另一个也使用的代码中导入这个项目libbar通过我的项目。

EDIT

我应该补充一点,这个问题不会出现在所有机器上。我在 Linux 机器上得到它,它也说

-- Set runtime path of "/PATH/TO/foo" to ""

在安装过程中。我在 Mac 上没有看到这条线,在 Mac 上根本不存在这个问题。

EDIT 2

我刚刚看到我的问题甚至在文档 https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling under 常见问题。他们还说添加set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)是解决方案。但这对我来说根本不起作用,我在这里做错了什么?

EDIT 3

难道是CMAKE_INSTALL_RPATH_USE_LINK_PATH = True解决方案在这里不起作用,因为我正在添加libbar via ExternalProject?该文档指出

CMAKE_INSTALL_RPATH_USE_LINK_PATH 是一个布尔值,如果设置为 true 将在链接器搜索路径中附加目录,并且项目外到 INSTALL_RPATH。这用于初始化所有目标的目标属性 INSTALL_RPATH_USE_LINK_PATH。


你的问题是not那个构建RPATH被删除。那些RPATHs 是构建目录的绝对路径,一旦离开您的机器就不起作用。无论如何,你不希望他们在那里。问题是你没有设置install RPATH正确。

在创建任何目标之前,将以下代码放在项目的早期位置。

include(GNUInstallDirs)

if (APPLE)
  set(rbase "@loader_path")
else ()
  set(rbase "$ORIGIN")
endif ()

file(RELATIVE_PATH lib_dir
     "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}"
     "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")

# Honor user overrides, whether at the command line or FetchContent
set(CMAKE_INSTALL_RPATH "${rbase};${rbase}/${libdir}"
    CACHE STRING "Install RPATH")

这会导致可重定位的安装树,并且对使用不同符号作为相对 RPATH 的 GNU 和 Apple 加载器实现都很敏感。

这还假设您的安装规则是标准的,并且会将运行时对象安装到CMAKE_INSTALL_BINDIR和图书馆CMAKE_INSTALL_LIBDIR。根据需要调整这些。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何避免在 CMake 安装步骤中删除 RPATH? 的相关文章

  • 为什么Apache MPM prefork.c 使用互斥体来保护accept()?

    我坐下来读书Apache 的 MPM prefork c http code metager de source xref apache httpd server mpm prefork prefork c这段代码使用了一个名为accept
  • 为什么大多数平台上没有“aligned_realloc”?

    MSVC有自己的非标准函数 aligned malloc aligned realloc and aligned free C 17和C11引入了 std aligned alloc 其结果可以是de分配有free or realloc B
  • (const T v) 在 C 中从来都不是必需的,对吗?

    例如 void func const int i 在这里 const是不必要的 因为所有参数都是按值传递的 包括指针 真的吗 C 中的所有参数确实都是按值传递 这意味着无论您是否包含该参数 实际参数都不会改变const or not 然而
  • mprotect 之后 malloc 导致分段错误

    在使用 mprotect 保护内存区域后第一次调用 malloc 时 我遇到分段错误 这是执行内存分配和保护的代码片段 define PAGESIZE 4096 void paalloc int size Allocates and ali
  • SFINAE 如何使用省略号?

    过去 当使用 SFINAE 选择构造函数重载时 我通常使用以下内容 template
  • 将字符串转换为正确的 URI 格式?

    有没有简单的方法可以将电子邮件地址字符串转换为正确的 URI 格式 Input http mywebsite com validate email 3DE4ED727750215D957F8A1E4B117C38E7250C33 email
  • 如何将带有自定义分配器的 std::vector 传递给需要带有 std::allocator 的函数?

    我正在使用外部库 pcl 因此我需要一个不会更改现有函数原型的解决方案 我正在使用的一个函数生成一个std vector
  • 劫持系统调用

    我正在编写一个内核模块 我需要劫持 包装一些系统调用 我正在暴力破解 sys call table 地址 并使用 cr0 来禁用 启用页面保护 到目前为止一切顺利 一旦完成 我将公开整个代码 因此如果有人愿意 我可以更新这个问题 无论如何
  • 对 boost 库的依赖项没有完整路径

    我已经成功构建了动态库 依赖于使用自定义前缀构建和安装的 boost 库 b2 install prefix PREFIX 然而 当我跑步时otool L在我的库中 我得到如下输出 libboost regex dylib compatib
  • 无法解析远程名称 - webclient

    我面临这个错误 The remote name could not be resolved russgates85 001 site1 smarterasp net 当我请求使用 Web 客户端读取 html 内容时 出现错误 下面是我的代
  • 从 Code::Blocks 运行程序时出现空白控制台窗口 [重复]

    这个问题在这里已经有答案了 当我尝试在 Code Blocks 中构建并运行新程序时 控制台窗口弹出空白 我必须单击退出按钮才能停止它 它对我尝试过的任何新项目 包括 Hello world 都执行此操作 奇怪的是 它对于我拥有的任何旧项目
  • 使用 WF 的多线程应用程序的错误处理模式?

    我正在写一个又长又详细的问题 但只是放弃了它 转而选择一个更简单的问题 但我在这里找不到答案 应用程序简要说明 我有一个 WPF 应用程序 它生成多个线程 每个线程执行自己的 WF 处理线程和 WF 中的错误 允许用户从 GUI 端进行交互
  • 为什么具有相同名称但不同签名的多个继承函数不会被视为重载函数?

    以下代码片段在编译期间产生 对 foo 的调用不明确 错误 我想知道是否有任何方法可以解决此问题而不完全限定对 foo 的调用 include
  • 如何随着分辨率的变化自动调整大小和调整表单控件

    我注意到某些应用程序会更改控件的位置以尽可能适应当前的分辨率 例如 如果窗口最大化 则控件的设置方式应使整个 GUI 看起来平衡 是否可以使用 C 在 Visual studio 2010 中制作或实现此功能 Use Dock http m
  • 二叉树中的 BFS

    我正在尝试编写二叉树中广度优先搜索的代码 我已将所有数据存储在队列中 但我不知道如何访问所有节点并消耗它们的所有子节点 这是我的 C 代码 void breadthFirstSearch btree bt queue q if bt NUL
  • asp.net网格分页的SQL查询

    我在用iBatis and SQLServer 使用偏移量和限制进行分页查询的最佳方法是什么 也许我添加该列ROW NUMBER OVER ORDER BY Id AS RowNum 但这只会阻止简单查询的数据访问 在某些情况下 我使用选择
  • 0-1背包算法

    以下 0 1 背包问题是否可解 浮动 正值和 浮动 权重 可以是正数或负数 背包的 浮动 容量 gt 0 我平均有 这是一个相对简单的二进制程序 我建议用蛮力进行修剪 如果任何时候你超过了允许的重量 你不需要尝试其他物品的组合 你可以丢弃整
  • Visual Studio 2017 完全支持 C99 吗?

    Visual Studio 的最新版本改进了对 C99 的支持 最新版本VS2017现在支持所有C99吗 如果没有 C99 还缺少哪些功能 No https learn microsoft com en us cpp visual cpp
  • 在 Xamarin 中获取 OutOfMemoryException

    java lang OutOfMemoryError 考虑增加 JavaMaximumHeapSize Java 执行时内存不足 java exe 我的 Visualstudio Xamarin 项目出现内存不足异常 请帮助我如何解决此问题
  • 以 UTF8 而不是 UTF16 输出 DataTable XML

    我有一个 DataTable 我正在使用 WriteXML 创建一个 XML 文件 尽管我在以 UTF 16 编码导出它时遇到问题 并且似乎没有明显的方法来更改它 我了解 NET 在字符串内部使用 UTF 16 这是正确的吗 然后 我通过

随机推荐