在 MacOS 上构建 conan/cmake 项目时的相对 RPATH
Relative RPATHs when building conan / cmake project on MacOS
我有一个简单的 C++ 项目,它依赖于 Intel TBB(需要使用共享库)。我正在尝试结合使用 Conan 包管理器和 CMake 来构建它,并且我已经能够使用此设置毫无问题地添加非共享依赖项。
我的第一次尝试(结合来自 conan's conanfile.txt documentation for using packages and conan's conanfile.py reference guide 的信息)使用了这样的 conanfile.py
:
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')
和这样的 CMakeLists.txt
:
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})
(我的src/main.cpp
只是the test file for the TBB package的直接复制)
这个构建得很好;
conan install -if build .
conan build -bf build .
但是 运行 ./build/bin/main
失败并出现以下错误:
dyld: Library not loaded: @rpath/libtbb.dylib
Referenced from: <project-dir>/./build/bin/main
Reason: image not found
Abort trap: 6
我在 MacOS 上,这个错误类似于 known (but apparently fixed) issue,所以我尝试 运行 从它自己的目录中获取二进制文件; cd build/bin; ./main
,却看到同样的错误。我不确定为什么这行不通,但我没有花太多时间调试就转向了另一种方法。
接下来我按照 conan documentation's "different approaches" for RPATHs guide 结束了这个:
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
还有这个:
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})
构建甚至运行!但是当我检查可执行文件时,我看到它引用了 /Users/me/.conan/data/TBB/2018_U6/conan/stable/package/03db91a62823ebc2b1df6e5cf549c2f674116656/lib
,这显然不是该代码应该做的(我期望看到 @rpath/../lib
或类似的)。我还验证了二进制文件确实在使用此路径,而不是放置在其同级 lib
文件夹中的文件。
此时我卡住了。我可以看到 CMake 有 a few options for RPATH handling,但没有什么看起来特别相关,我不明白为什么我第二次尝试的代码(直接取自柯南的文档)不起作用。
我需要做什么才能让共享库与柯南一起使用? (最好是跨平台,但至少在 MacOS 上)
我在一次又一次地查看 CMake 的 other variables 后,在第二次尝试中找出了问题。
缺少的设置是这样的:
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
希望这可以添加到 Conan 文档中,因为启用它后一切都可以正常工作。作为最终参考,我的构建文件是:
conanfile.py
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='lib')
self.copy('*.so', src='lib', dst='lib')
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(MyProject)
add_definitions("-std=c++11") # to use 17, must also set '-s cppstd=17' on conan install
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()
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) # <-- this is the line which is missing in the Conan documentation!
add_executable(main src/main.cpp)
target_link_libraries(main ${CONAN_LIBS})
构建
conan install -if build .
conan build -bf build .
运行 和
./build/bin/main
只要生成的 bin 和 lib 目录保持兄弟关系,它就会正常工作。输出二进制文件只包含相对路径;没有特定于机器的路径。
我有一个简单的 C++ 项目,它依赖于 Intel TBB(需要使用共享库)。我正在尝试结合使用 Conan 包管理器和 CMake 来构建它,并且我已经能够使用此设置毫无问题地添加非共享依赖项。
我的第一次尝试(结合来自 conan's conanfile.txt documentation for using packages and conan's conanfile.py reference guide 的信息)使用了这样的 conanfile.py
:
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')
和这样的 CMakeLists.txt
:
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})
(我的src/main.cpp
只是the test file for the TBB package的直接复制)
这个构建得很好;
conan install -if build .
conan build -bf build .
但是 运行 ./build/bin/main
失败并出现以下错误:
dyld: Library not loaded: @rpath/libtbb.dylib Referenced from: <project-dir>/./build/bin/main Reason: image not found Abort trap: 6
我在 MacOS 上,这个错误类似于 known (but apparently fixed) issue,所以我尝试 运行 从它自己的目录中获取二进制文件; cd build/bin; ./main
,却看到同样的错误。我不确定为什么这行不通,但我没有花太多时间调试就转向了另一种方法。
接下来我按照 conan documentation's "different approaches" for RPATHs guide 结束了这个:
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
还有这个:
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})
构建甚至运行!但是当我检查可执行文件时,我看到它引用了 /Users/me/.conan/data/TBB/2018_U6/conan/stable/package/03db91a62823ebc2b1df6e5cf549c2f674116656/lib
,这显然不是该代码应该做的(我期望看到 @rpath/../lib
或类似的)。我还验证了二进制文件确实在使用此路径,而不是放置在其同级 lib
文件夹中的文件。
此时我卡住了。我可以看到 CMake 有 a few options for RPATH handling,但没有什么看起来特别相关,我不明白为什么我第二次尝试的代码(直接取自柯南的文档)不起作用。
我需要做什么才能让共享库与柯南一起使用? (最好是跨平台,但至少在 MacOS 上)
我在一次又一次地查看 CMake 的 other variables 后,在第二次尝试中找出了问题。
缺少的设置是这样的:
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
希望这可以添加到 Conan 文档中,因为启用它后一切都可以正常工作。作为最终参考,我的构建文件是:
conanfile.py
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='lib')
self.copy('*.so', src='lib', dst='lib')
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(MyProject)
add_definitions("-std=c++11") # to use 17, must also set '-s cppstd=17' on conan install
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()
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) # <-- this is the line which is missing in the Conan documentation!
add_executable(main src/main.cpp)
target_link_libraries(main ${CONAN_LIBS})
构建
conan install -if build .
conan build -bf build .
运行 和
./build/bin/main
只要生成的 bin 和 lib 目录保持兄弟关系,它就会正常工作。输出二进制文件只包含相对路径;没有特定于机器的路径。