5

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 
Gabriel
  • 8,990
  • 6
  • 57
  • 101
  • Looks like https://github.com/conan-io/cmake-conan#keep_rpaths is what you need. I don't have experience with conan, but looking on the path to package it seems they have reasons to remove conan-based paths. – Nickolay Olshevsky Dec 06 '21 at 14:21
  • But I am questioning, which Cmake code produces this behavior. I dont see anything suspicious in the Findfmt.cmake script generated from Conan. ? – Gabriel Dec 06 '21 at 14:37
  • @NickolayOlshevsky: `KEEP_RPATHS` is not used in this approach by Conan.cmake and has no effect. – Gabriel Dec 06 '21 at 14:45
  • It's somewhere inside `conan.cmake` script you are downloading. Wasn't able to quickly trace it, but this page describes behaviour: https://docs.conan.io/en/latest/howtos/manage_shared_libraries/rpaths.html?highlight=keep_rpath – Nickolay Olshevsky Dec 06 '21 at 14:45
  • @NickolayOlshevsky No its not there, its not respected, and has no impact. Only CMake is involved once conan install has been run. – Gabriel Dec 06 '21 at 18:24

1 Answers1

1

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?).

Gabriel
  • 8,990
  • 6
  • 57
  • 101