nor*_*ius 7 macos cmake shared-libraries dylib vtk
在 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
Run Code Online (Sandbox Code Playgroud)
我能够在由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}")
Run Code Online (Sandbox Code Playgroud)
该main.cpp甚至没有利用任何VTK对象。
// main.cpp
#include <iostream>
int main (int argc, char* argv[])
{
std::cout << "Hello world!" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我使用以下命令构建项目。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
Run Code Online (Sandbox Code Playgroud)
testapp在 build 文件夹中执行时,一切看起来都很好:
$ ./testapp
Hello world!
$ cp testapp $INSTALLDIR/testapp
$ $INSTALLDIR/testapp
Hello world!
Run Code Online (Sandbox Code Playgroud)
但是,如果我在 中运行可执行文件,则会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
Run Code Online (Sandbox Code Playgroud)
当然,问题消失,如果我删除target_link_libraries()的指令CMakeLists.txt。
那么在安装 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)
...
Run Code Online (Sandbox Code Playgroud)
因为它可能会影响 VTK 库(另一个 CMake 项目)的构建方式:对于 Python 支持,必须设置项目标志VTK_WRAP_PYTHON=ON和BUILD_SHARED_LIBS=ON. 安装前缀设置为CMAKE_INSTALL_PREFIX="$VTK_INSTALL_DIR". 为了确保在运行时找到资源,必须另外通过CMAKE_MACOSX_RPATH=ON和启用 RPATH 支持CMAKE_INSTALL_RPATH="$VTK_INSTALL_DIR/lib"。
我在概念上犯了什么错误?安装项目时会发生什么make install?这个问题可以在 CMake 中解决吗?还是仅与 VTK 以及共享库的构建方式有关?
CMake 在运行时更改所有已安装目标的 RPATH make install。
想象一下,构建一个共享库和一个可执行文件作为同一个 CMake 项目的一部分。为了能够运行可执行文件,它必须能够在运行时动态加载共享库。因此,默认情况下,CMake 会将构建树中动态库的完整(绝对)路径添加到可执行文件的 rpath。这对于开发来说非常方便,因为我们可以直接从构建树运行可执行文件,但我们可能不希望以这种方式发布可执行文件。
这就是为什么 CMake 在安装时将 rpath 更改为仅包含可移植路径的原因(即删除指向构建树的条目)。也就是说,除非您将共享库放入系统默认位置之一,否则安装后可执行文件将不再找到它。
CMake 确实允许您指定一个安装 rpath,该路径将用您指定的构建树条目替换已删除的构建树条目。有关详细信息,请参阅INSTALL_RPATH和INSTALL_RPATH_USE_LINK_PATH目标属性。
因为所有这些 rpath 的东西都是 100% 依赖于平台的,所以 OSX 有它自己的特殊规则。在(不幸的是相当过时的)CMake wiki上可以找到一个非常全面的解释:
与其他 UNIX 不同,Darwin 链接器 dyld 使用每个 dylib 的完整路径来定位依赖的动态库。例如,在可执行文件“foo”中,记录的完整路径是每个依赖 dylib 的安装名称。并且库“/usr/lib/libSystem.dylib”的安装名称为“/usr/lib/libSystem.B.dylib”,由“otool -D”给出。当链接到“foo”时,“foo”依赖于“/usr/lib/libSystem.B.dylib”。这种依赖可以通过“otool -L foo”看到。对于可重定位的二进制文件,可以使用 @executable_path、@loader_path 和 @rpath。在“foo”示例中,@executable_path 和@loader_path 被替换为“foo”的位置。@rpath 替换为“foo”中的 RPATH 以定位依赖的 dylib。因此 RPATH 机制开始发挥作用。链接器将按以下顺序搜索 @rpath/ 依赖项:
- DYLD_LIBRARY_PATH - 保存目录列表的环境变量
- RPATH - 链接到可执行文件的目录列表。这些可以包含@loader_path 和@executable_path。
- 内置目录 - /lib /usr/lib
- DYLD_FALLBACK_LIBRARY_PATH - 保存目录列表的环境变量
您应该能够通过调整各自的目标属性来解决这个问题,但它相当繁琐,而且很难做到正确。
| 归档时间: |
|
| 查看次数: |
5434 次 |
| 最近记录: |