问题
在MacOS上,我在依赖于动态链接资源的CMake项目运行时遇到了连接问题——但仅在安装该项目后才会出现!如果只构建二进制文件而未将其安装,则不会出现此问题。
$ ./testapp
Hello world!
$ $INSTALLDIR/testapp
dyld: Library not loaded: @rpath/libvtkDomainsChemistryOpenGL2-7.1.1.dylib
Referenced from: /Users/normanius/workspace/installdir/testapp
Reason: image not found
[1] 76964 trace trap /Users/normanius/workspace/installdir/testapp
最简单的例子
我能够在一个最小的设置中重现问题,该设置由CMakeLists.txt
和main.cpp
组成。我链接的库叫做VTK(v7.1.1),它已经使用共享库构建(有关更多详细信息,请参见下文)。
# CMakeLists.txt
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(test)
# Test application.
add_executable(testapp
main.cpp)
# Find vtk (library that has to be linked to dynamically).
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
target_link_libraries(testapp ${VTK_LIBRARIES}) # <---- this causes the problem
# Install instructions.
install(TARGETS testapp DESTINATION "${CMAKE_INSTALL_PREFIX}")
main.cpp
并没有使用任何VTK对象。
// main.cpp
#include <iostream>
int main (int argc, char* argv[])
{
std::cout << "Hello world!" << std::endl;
return 0;
}
我使用以下命令构建项目。 我设置了标志CMAKE_PREFIX_PATH
,以向CMake提供有关在哪里找到VTK库的提示。
$ INSTALLDIR="path/to/installation"
$ mkdir build && cd build
$ cmake .. -DCMAKE_PREFIX_PATH="$DEVPATH/lib/vtk/cmake" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$INSTALLDIR"
$ make
$ make install
当在构建文件夹中执行
testapp
时,一切看起来都很好:$ ./testapp
Hello world!
$ cp testapp $INSTALLDIR/testapp
$ $INSTALLDIR/testapp
Hello world!
然而,如果我在 INSTALLDIR
中运行可执行文件,会出现运行时错误:
$ $INSTALLDIR/testapp
dyld: Library not loaded: @rpath/libvtkDomainsChemistryOpenGL2-7.1.1.dylib
Referenced from: /Users/normanius/workspace/installdir/testapp
Reason: image not found
[1] 76964 trace trap /Users/normanius/workspace/installdir/testapp
当我在
CMakeLists.txt
中删除 target_link_libraries()
指令时,问题自然而然地消失了。那么安装 CMake 项目时到底会发生什么?我的情况出了什么问题?我测试了不同的 CMake 版本(3.5、3.9 和 3.10),但行为都是相同的。
详情:
显然,在 MacOS 上,示例的 RPATH 机制没有正确设置。
这是
testapp
二进制链接结构的摘录:$ otool -L testapp
testapp:
@rpath/libvtkDomainsChemistryOpenGL2-7.1.1.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libvtkFiltersFlowPaths-7.1.1.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libvtkFiltersGeneric-7.1.1.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libvtkFiltersHyperTree-7.1.1.dylib (compatibility version 0.0.0, current version 0.0.0)
...
由于这可能会影响VTK库(另一个CMake项目)的构建方式:为了支持Python,必须设置项目标志
VTK_WRAP_PYTHON=ON
和BUILD_SHARED_LIBS=ON
。安装前缀设置为CMAKE_INSTALL_PREFIX="$VTK_INSTALL_DIR"
。为确保在运行时找到资源,还必须通过CMAKE_MACOSX_RPATH=ON
和CMAKE_INSTALL_RPATH="$VTK_INSTALL_DIR/lib"
启用RPATH支持。
总结
当使用make install
安装项目时,我有什么概念上的错误?这会发生什么?这个问题可以在CMake中解决吗?还是只与VTK以及共享库的构建方式有关?
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH="ON"
,问题就解决了! - normaniusDYLD_LIBRARY_PATH
技巧,但这个“hack”并不总是有效,因为苹果引入了系统完整性保护,这是我在早期的SO帖子中处理过的问题。 - normanius