c++ - 在 MacOS 上构建 conan/cmake 项目时的相对 RPATH

标签 c++ cmake shared-libraries macos-high-sierra conan

我有一个简单的 C++ 项目,它依赖于英特尔 TBB(需要使用共享库)。我正在尝试结合使用 Conan 包管理器和 CMake 来构建它,并且我已经能够使用此设置毫无问题地添加非共享依赖项。


我的第一次尝试(结合来自 conan's conanfile.txt documentation for using packagesconan'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 ,但没有什么看起来特别相关,我不明白为什么我第二次尝试的代码(直接取自柯南的文档)不起作用。

我需要做什么才能让共享库与 conan 一起使用? (理想情况下是跨平台的,但至少在 MacOS 上)

最佳答案

在查看 CMake 的 other variables 后,我在第二次尝试中发现了问题。一个接一个。

缺少的设置是这样的:

set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)

希望这可以添加到 Conan 文档中,因为有了它,一切都可以正常工作。作为最终引用,我的构建文件是:

柯南文件.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++ - 在 MacOS 上构建 conan/cmake 项目时的相对 RPATH,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53459518/

相关文章:

java - JNA Native.loadLibrary产生内存故障: __memmove_avx_unaligned_erms

c++ - 如何命名某个目录下的文本文件?

C++ 和通用图距离算法

c++ - CMake 在 Ubuntu 中找不到 GoogleTest 所需的库

找不到 CMake 库

linux - 带有两个共享库的 dlopen,导出符号

c - 字符串 linux 工具中未隐藏剥离的符号

c++ - 来自 T* 的 std::unique_ptr<T> 的构造函数是显式的背后的原因是什么?

c++ - 二分查找,排序数组

cmake - 不同目标中同一文件的不同编译标志