Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake not adding full RPATH on macOS

Tags:

c++

cmake

rpath

I have the following MWE where Conan is used to install the fmt library (shared).

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)

When I inspect the executable otool -l main I see that the fmt library has no absolute path, which I expect to happen. So also the executbale can not be run, because it doesn find libfmtd.6.dylib.

The question is, what is wrongly setup here and why is there no full path encoded in the executable?

Output 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

The link command has been:

/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 
like image 360
Gabriel Avatar asked Nov 05 '22 23:11

Gabriel


1 Answers

The problem lies probably in the fact how conan builds fmt during conan_cmake_install It builds it without RPATHs meaning, the resulting fmt library contains a LC_ID_DYLIB section:

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

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

And this path name libfmtd.8.dylib ... gets embedded in the executable main.

The library fmt should have been built with RPATH enabled resulting in a

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

together with an additional RPATH in the executable main which will point to"

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

which will be added by cmake automatically (IMO?).

like image 69
Gabriel Avatar answered Nov 13 '22 06:11

Gabriel