I have a simple C++ project with a dependency on Intel TBB (which requires the use of shared libraries). I'm trying to build this using the Conan package manager combined with CMake, and I've already been able to use this setup to add non-shared dependencies with no problems.
My first attempt (combining the information from conan's conanfile.txt documentation for using packages and conan's conanfile.py reference guide) used a conanfile.py
like this:
import os
from conans import ConanFile, CMake
class MyProjectConan(ConanFile):
settings = 'os', 'compiler', 'build_type', 'arch'
requires = 'TBB/2018_U6@conan/stable'
generators = 'cmake'
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def imports(self):
self.copy('*.dll', src='bin', dst='bin')
self.copy('*.dylib*', src='lib', dst='bin')
self.copy('*.so', src='lib', dst='bin')
and a CMakeLists.txt
like this:
cmake_minimum_required(VERSION 2.8.12)
project(MyProject)
add_definitions("-std=c++17")
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
add_executable(main src/main.cpp)
target_link_libraries(main ${CONAN_LIBS})
(my src/main.cpp
is just a direct copy of the test file for the TBB package)
This built just fine;
conan install -if build .
conan build -bf build .
But running ./build/bin/main
failed with this error:
dyld: Library not loaded: @rpath/libtbb.dylib Referenced from: <project-dir>/./build/bin/main Reason: image not found Abort trap: 6
I'm on MacOS, and this error is similar to a known (but apparently fixed) issue, so I tried running the binary from its own directory; cd build/bin; ./main
, but saw the same error. I'm not sure why this didn't work, but I moved on to another approach without spending much time debugging it.
Next I followed the conan documentation's "different approaches" for RPATHs guide to end up with this:
class MyProjectConan(ConanFile):
# (rest of class is same as before)
def imports(self):
self.copy('*.dll', src='bin', dst='bin')
self.copy('*.dylib*', src='lib', dst='lib') # changed bin to lib
self.copy('*.so', src='lib', dst='lib') # changed bin to lib
and this:
cmake_minimum_required(VERSION 2.8.12)
project(MyProject)
add_definitions("-std=c++17")
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(KEEP_RPATHS)
if(APPLE)
set(CMAKE_INSTALL_RPATH "@executable_path/../lib")
else()
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
endif()
add_executable(main src/main.cpp)
target_link_libraries(main ${CONAN_LIBS})
Which builds and even runs! But when I inspect the executable I see that it references /Users/me/.conan/data/TBB/2018_U6/conan/stable/package/03db91a62823ebc2b1df6e5cf549c2f674116656/lib
, which is obviously not what that code is supposed to do (I was expecting to see @rpath/../lib
or similar). I have also verified that the binary is indeed using this path, and not the files placed in its sibling lib
folder.
At this point I'm stuck. I can see that CMake has a few options for RPATH handling, but nothing there looks particularly relevant, and I don't understand why the code in my second attempt (taken directly from conan's documentation) doesn't work.
What do I need to do to get a shared library working with conan? (ideally cross-platform, but at least on MacOS)