OS X El Capitan 上的 dlopen 错误 "unsafe use of relative rpath"
dlopen error "unsafe use of relative rpath" on OS X El Capitan
我一直在开发两个由 CMake 构建的 C++ 库。其中一个库 (ProjectB) 有一个由 SWIG 生成的 Python 包装器,它依赖于另一个库 (ProjectA)。
这些库在 Linux 和 OS X Yosemite 或更早版本上运行良好。但是当我在 El Capitan 上导入 ProjectB 的 Python 包装器时出现以下错误。
$ python
>>> import project_b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "project_b.py", line 28, in <module>
_project_b = swig_import_helper()
File "project_b.py", line 24, in swig_import_helper
_mod = imp.load_module('_project_b', fp, pathname, description)
ImportError: dlopen(./_project_b.so, 2): Library not loaded: libProjectA.dylib
Referenced from: /Users/oxon/cmake_test/ProjectB_build/_project_b.so
Reason: unsafe use of relative rpath libProjectA.dylib in ./_project_b.so with restricted binary
我认为这与El Capitan新的安全技术有关,安装在/usr/local/lib
下的动态库如果通过相对路径调用是无法加载的。事实上,otool -L
显示我的 Python 包装器 (_project_b.so
) 有一个到 ProjectA 的相对路径(libProjectA.dylib
安装在 /usr/local/lib
下)。
$ otool -L _project_b.so
_project_b.so:
/System/Library/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.10)
libProjectA.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
问题: 我想知道如何通过修改我在这些项目中的 CMakeLists.txt 来修复这个错误。我如何通过绝对路径link libProjectA.dylib
?
我知道install_name_tool
命令可以把相对路径改成绝对路径。但我不想让我的图书馆的用户每次都这样做。所以我想在 CMakeLists.txt.
中解决这个问题
ProjectB/exeB
,但是,即使它也使用 libProjectB.dylib
和 libProjectA.dylib
.
,也可以在没有 rpath 问题的情况下正常工作
下面是ProjectA的目录结构,
ProjectA
├── CMakeLists.txt
├── ProjectAConfig.cmake
├── include
│ └── ProjectA
│ └── MyClassA.h
└── src
└── MyClassA.cxx
和 ProjectB.
ProjectB
├── CMakeLists.txt
├── exeB.cxx
├── include
│ └── ProjectB
│ └── MyClassB.h
├── project_b.i
└── src
└── MyClassB.cxx
我按照以下步骤完成了构建过程。
$ pwd
/Users/oxon/cmake_test
$ ls
ProjectA ProjectA_build ProjectB ProjectB_build
$ cd ProjectA_build
$ cmake ../ProjectA
$ make
$ sudo make install
$ cd ../ProjectB_build
$ cmake ../ProjectB
$ make
$ python
>>> import project_b
你可以从下载我的最小示例
https://github.com/akira-okumura/Whosebug_question
在 ProjectB/CMakeLists.txt
中添加以下行已解决问题。
if(APPLE)
set(CMAKE_MACOSX_RPATH TRUE)
# The following settings were copied from
# https://cmake.org/Wiki/CMake_RPATH_handling
# to avoid the rpath issue that appears on OS X El Capitan
# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) # Changed to TRUE by A.O.
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# the RPATH to be used when installing, but only if it's not a system directory
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif("${isSystemDir}" STREQUAL "-1")
endif()
CMAKE_BUILD_WITH_INSTALL_RPATH
选项从 FALSE
更改为 TRUE
以允许用户在安装 ProjectB 库之前在构建目录下测试 import project_b
。
我一直在开发两个由 CMake 构建的 C++ 库。其中一个库 (ProjectB) 有一个由 SWIG 生成的 Python 包装器,它依赖于另一个库 (ProjectA)。
这些库在 Linux 和 OS X Yosemite 或更早版本上运行良好。但是当我在 El Capitan 上导入 ProjectB 的 Python 包装器时出现以下错误。
$ python
>>> import project_b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "project_b.py", line 28, in <module>
_project_b = swig_import_helper()
File "project_b.py", line 24, in swig_import_helper
_mod = imp.load_module('_project_b', fp, pathname, description)
ImportError: dlopen(./_project_b.so, 2): Library not loaded: libProjectA.dylib
Referenced from: /Users/oxon/cmake_test/ProjectB_build/_project_b.so
Reason: unsafe use of relative rpath libProjectA.dylib in ./_project_b.so with restricted binary
我认为这与El Capitan新的安全技术有关,安装在/usr/local/lib
下的动态库如果通过相对路径调用是无法加载的。事实上,otool -L
显示我的 Python 包装器 (_project_b.so
) 有一个到 ProjectA 的相对路径(libProjectA.dylib
安装在 /usr/local/lib
下)。
$ otool -L _project_b.so
_project_b.so:
/System/Library/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.10)
libProjectA.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
问题: 我想知道如何通过修改我在这些项目中的 CMakeLists.txt 来修复这个错误。我如何通过绝对路径link libProjectA.dylib
?
我知道install_name_tool
命令可以把相对路径改成绝对路径。但我不想让我的图书馆的用户每次都这样做。所以我想在 CMakeLists.txt.
ProjectB/exeB
,但是,即使它也使用 libProjectB.dylib
和 libProjectA.dylib
.
下面是ProjectA的目录结构,
ProjectA
├── CMakeLists.txt
├── ProjectAConfig.cmake
├── include
│ └── ProjectA
│ └── MyClassA.h
└── src
└── MyClassA.cxx
和 ProjectB.
ProjectB
├── CMakeLists.txt
├── exeB.cxx
├── include
│ └── ProjectB
│ └── MyClassB.h
├── project_b.i
└── src
└── MyClassB.cxx
我按照以下步骤完成了构建过程。
$ pwd
/Users/oxon/cmake_test
$ ls
ProjectA ProjectA_build ProjectB ProjectB_build
$ cd ProjectA_build
$ cmake ../ProjectA
$ make
$ sudo make install
$ cd ../ProjectB_build
$ cmake ../ProjectB
$ make
$ python
>>> import project_b
你可以从下载我的最小示例 https://github.com/akira-okumura/Whosebug_question
在 ProjectB/CMakeLists.txt
中添加以下行已解决问题。
if(APPLE)
set(CMAKE_MACOSX_RPATH TRUE)
# The following settings were copied from
# https://cmake.org/Wiki/CMake_RPATH_handling
# to avoid the rpath issue that appears on OS X El Capitan
# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) # Changed to TRUE by A.O.
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# the RPATH to be used when installing, but only if it's not a system directory
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif("${isSystemDir}" STREQUAL "-1")
endif()
CMAKE_BUILD_WITH_INSTALL_RPATH
选项从 FALSE
更改为 TRUE
以允许用户在安装 ProjectB 库之前在构建目录下测试 import project_b
。