避免针对@rpath的 CMAKE 链接,而是使用绝对路径

Avoid CMAKE linking against @rpath and use absolute paths instead

提问人:nano 提问时间:11/14/2023 最后编辑:nano 更新时间:11/15/2023 访问量:65

问:

我正在构建一个 CMAKE 可执行文件并链接到外部库。

对于该库,我有一个自定义的 FindMYLIB cmake scribt,可以成功设置变量。PROMTINGMYLIB_LIBRARIES

MESSAGE("${MYLIB_LIBRARIES}")

正确屈服

/usr/local/lib/libmylib.dylib

我使用

target_link_libraries(my_executable
        ${MYLIB_LIBRARIES}
        )

在我的工具链或CMAKE代码中,没有设置任何自定义设置。RPATH

问题

运行它给了我错误

dyld[94833]: Library not loaded: @rpath/libmylib.dylib
  Referenced from: <3747E824-3D4B-38A3-BFD8-E96891349DD5> /path/to/my_executable
  Reason: no LC_RPATH's found

在检查链接的内容时,我阅读了

$ otool -L /path/to/my_executable
/path/to/my_executable:
    ...
    @rpath/libmylib.dylib (compatibility version 0.0.0, current version 0.0.0)
    ...
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1600.151.0)

以下情况不会发生,并且缺少

$ otool -l /path/to/my_executable
[...]
Load command NN
          cmd LC_RPATH
      cmdsize 32
         path /usr/local/lib (offset 12)

缓解

我发现以下方法通过显式设置来修复可执行文件:LC_RPATH

install_name_tool -add_rpath /usr/local/lib /pyth/to/my_executable

问题

如何首先避免使用链接,而是使用绝对路径?既然 CMAKE 拥有绝对路径,那么它们如何最终成为相对链接?@rpath

在另一台机器上构建相同的路径只会生成绝对路径。

设置

Mac OSX,M1 CMake 3.23.2 苹果克朗 15

更多细节

我有一个象征性的链接libmylib.dylib -> libmylib-XX.YY.ZZ.dylib

第一个出现在 CMAKE 中,第二个作为链接名称出现。

目前未成功

多个 CMAKE 标志,包括CMAKE_SKIP_RPATH

编辑 1

set(CMAKE_EXE_LINKER_FLAGS "-Wl,-rpath,/usr/local/lib")

使可执行文件运行。

它缓解了没有 rpath 的问题,但不能解决我安装 rpath 的问题。/usr/local/lib

编辑 2

最小示例

# CMakeLists.txt

cmake_minimum_required(VERSION 3.12)
project(test_exe)

add_executable(test_exe main.cpp)

target_include_directories(test_exe
        PRIVATE /usr/local/include)

target_link_libraries(test_exe
        PRIVATE
        /usr/local/lib/libmylib.dylib
        )
// main.cpp

#include <mylib/version.hxx>

int main()
{
    return 0;
}

连接:

/usr/bin/c++
    -g
    -arch
    arm64
    -isysroot
    /Library/Developer/CommandLineTools/SDKs/MacOSX14.0.sdk
    -Wl,-search_paths_first
    -Wl,-headerpad_max_install_names

    CMakeFiles/test_exe.dir/main.cpp.o
    -o
    test_exe

    /usr/local/lib/libmylib.dylib
$ otool -L ./cmake-build-debug/test_exe

    @rpath/libmylib.dylib (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1600.151.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.0.0)

编辑 3

$ otool -L /usr/local/lib/libmylib.dylib

    @rpath/libmylib.dylib (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1600.151.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.0.0)

因此,该库将自己的名字称为 rpath-stuff。

重命名其内部使用

install_name_tool -id
    /usr/local/lib/libmylib.dylib
    /usr/local/lib/libmylib.dylib

在某些情况下,让它指向其绝对路径可以解决问题。

我的可执行文件链接到并找到它。/usr/local/lib/libmylib.dylib

但它仍然无法运行,因为其他几个 .dylib 被引用。我必须破解所有这些。这里的关键问题是我对我的包提供者 (build2) 构建库的方式不满意。libmylib.dylib

C++ macOS CMake RPATH

评论

0赞 n. m. could be an AI 11/14/2023
第一步,执行详细的构建并查看由 执行的 link 命令。你发现其中有什么问题吗?make
0赞 n. m. could be an AI 11/14/2023
问题可能是默认情况下链接器搜索的位置,而不是运行时链接器/加载程序搜索的位置。因此,不建议将共享/动态库安装到 。你要么需要添加你构建的所有内容,要么修改系统范围的动态加载器配置(不知道它在Mac OS上的位置,但在许多系统上它都在)。/usr/local/lib/usr/local/librpath/etc/ld.so.conf
1赞 Tsyvarev 11/14/2023
默认情况下,对于构建树中的可执行文件,CMake 会为 RPATH 中的链接库添加绝对路径安装这些可执行文件时,CMake 会从 RPATH 中剥离这些绝对路径。例如,此处描述了此行为:gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/...。那么,哪个确切的可执行文件具有意外的 RPATH,是构建树中的可执行文件,还是安装树中的可执行文件?
0赞 n. m. could be an AI 11/14/2023
好吧,显然Mac OS X与其他所有东西都太大不同,所以我之前的评论可能不适用。
0赞 nano 11/14/2023
详细转储的简短版本如下:''' /Library/Developer/CommandLineTools/usr/bin/c++ [...] -Wl,-search_paths_first -Wl,-headerpad_max_install_names [...所有 cpp.o 文件] -o my_executable -L/opt/homebrew/lib -L/opt/homebrew/opt/libomp/lib -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/opt/homebrew/opt/libomp/lib [...其他库] /usr/local/lib/libmylib.dylib [...] ''' 在我的 CMake 中,我有 ''' link_directories(/usr/local/lib) link_directories(/opt/homebrew/lib) list(APPEND CMAKE_PREFIX_PATH “/opt/homebrew/”) '''

答: 暂无答案