CMake 没有在 macOS 上添加完整的 RPATH

Posted

技术标签:

【中文标题】CMake 没有在 macOS 上添加完整的 RPATH【英文标题】:CMake not adding full RPATH on macOS 【发布时间】:2022-01-11 17:05:01 【问题描述】:

我有以下 MWE,其中柯南用于安装 fmt 库(共享)。

cmake_minimum_required(VERSION 3.21)
project(Test CXX)

set(CMAKE_MACOSX_RPATH ON)
set(CMAKE_CXX_STANDARD 17)

list(APPEND CMAKE_MODULE_PATH $CMAKE_BINARY_DIR)
list(APPEND CMAKE_PREFIX_PATH $CMAKE_BINARY_DIR)

if(NOT EXISTS "$CMAKE_BINARY_DIR/conan.cmake")
  message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
  file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/v0.16.1/conan.cmake"
                "$CMAKE_BINARY_DIR/conan.cmake"
                EXPECTED_HASH SHA256=396e16d0f5eabdc6a14afddbcfff62a54a7ee75c6da23f32f7a31bc85db23484
                TLS_VERIFY ON)
endif()

include($CMAKE_BINARY_DIR/conan.cmake)

conan_cmake_configure(REQUIRES fmt/6.1.2
                      OPTIONS fmt:shared=True
                      GENERATORS cmake_find_package)

conan_cmake_autodetect(settings)

conan_cmake_install(PATH_OR_REFERENCE .
                    BUILD missing
                    REMOTE conancenter
                    SETTINGS $settings)

find_package(fmt)

add_executable(main main.cpp)
target_link_libraries(main fmt::fmt)

当我检查可执行文件 otool -l main 时,我看到了 fmt 库没有绝对路径,我希望这会发生。 所以这个可执行文件也无法运行,因为它没有找到libfmtd.6.dylib

问题是,这里的设置有什么错误,为什么可执行文件中没有完整路径编码?

输出otool

Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 40
         name libfmtd.6.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 6.1.2
compatibility version 6.0.0
Load command 14
          cmd LC_LOAD_DYLIB
      cmdsize 48
         name /usr/lib/libc++.1.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1200.3.0
compatibility version 1.0.0
Load command 15
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1311.0.0
compatibility version 1.0.0

链接命令是:

/usr/local/Cellar/cmake/3.21.4/bin/cmake -E cmake_link_script CMakeFiles/main.dir/link.txt --verbose=1
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -g 
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk 
-mmacosx-version-min=11.4 -Wl,-search_paths_first 
-Wl,-headerpad_max_install_names 
CMakeFiles/main.dir/main.cpp.o 
-o main  
/Users/.../.conan/data/fmt/6.1.2/_/_/package/8cb4659713397fdd78e4947cac0468f7f7ca515d/lib/libfmtd.dylib 

【问题讨论】:

看起来github.com/conan-io/cmake-conan#keep_rpaths 是您所需要的。我没有使用柯南的经验,但是查看打包路径似乎他们有理由删除基于柯南的路径。 但我在质疑,哪个 Cmake 代码会产生这种行为。我在柯南生成的 Findfmt.cmake 脚本中没有看到任何可疑之处。 ? @NickolayOlshevsky: KEEP_RPATHS 没有被 Conan.cmake 用于这种方法,并且没有任何效果。 它位于您正在下载的 conan.cmake 脚本中的某个位置。无法快速追踪它,但此页面描述了行为:docs.conan.io/en/latest/howtos/manage_shared_libraries/… @NickolayOlshevsky 不,它不存在,它不被尊重,也没有影响。运行 conan install 后,仅涉及 CMake。 【参考方案1】:

问题可能在于柯南在conan_cmake_install期间如何构建fmt 它在没有 RPATH 含义的情况下构建它,生成的 fmt 库包含 LC_ID_DYLIB 部分:

otool -L /Users/.../.conan/data/fmt/8.0.1/_/_/package/09858fb580f8c1d91b81bfdbedd881822cc5da84/lib/libfmtd.dylib 给出:

Load command 4
          cmd LC_ID_DYLIB
      cmdsize 40
         name libfmtd.8.dylib (offset 24)
   time stamp 1 Thu Jan  1 01:00:01 1970
      current version 8.0.1
compatibility version 8.0.0

并且这条路径 name libfmtd.8.dylib ... 被嵌入到可执行文件 main 中。

库 fmt 应该在启用 RPATH 的情况下构建,从而导致

Load command 4
          cmd LC_ID_DYLIB
      cmdsize 40
         name @rpath/libfmtd.8.dylib (offset 24)

与可执行文件main 中的附加 RPATH 一起指向“”

/Users/.../.conan/data/fmt/8.0.1/_/_/package/09858fb580f8c1d91b81bfdbedd881822cc5da84/lib/

cmake 会自动添加(IMO?)。

【讨论】:

以上是关于CMake 没有在 macOS 上添加完整的 RPATH的主要内容,如果未能解决你的问题,请参考以下文章

CMake 在 macOS 上找不到 libevent

Big Sur 内置的 CMake MacOS 应用程序无法在 Catalina 上运行

如何强制 cmake 在没有完整路径的情况下使用 cl.exe?

MacOS、CMake 和 OpenMP

cmake find_package脚本只能在Linux上失败

MacOS | Axure RP Pro / Team / Enterprise v9.0.0.3648