在MacOS上构建柯南/ CMake项目时的相对RPATH

时间:2018-11-24 15:12:32

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

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


我的第一次尝试(结合来自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,但是看起来没有什么特别重要,而且我不理解为什么第二次尝试中的代码(直接从柯南的文档中获取)不起作用。

要使共享库与柯南一起工作,我需要怎么做? (理想情况下是跨平台的,但至少在MacOS上如此)

1 个答案:

答案 0 :(得分:3)

在逐一查看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目录仍然是同级,它就可以正常工作。输出二进制仅包含相对路径;没有机器专用的路径。