自 Mac OS 10.11 El Capitan 起具有系统完整性保护的 DYLD_LIBRARY_PATH 技巧的替代方案

nor*_*ius 6 python macos dyld vtk

这是我所拥有的:

  • Mac OS 10.11 El Capitan
  • python 2.7.12,从python.org下安装 /Library/Frameworks/Python.framework/
  • PyCharm 2016.2.3
  • vtk 7.1.0

这是我所做的:

  • 在本地构建一个 python 模块。就我而言,这是vtk。有关摘要,请参阅我配置 vtk 的 CMake 调用。

    cmake -G Ninja .. -DCMAKE_BUILD_TYPE=Release -DVTK_WRAP_PYTHON=ON -DBUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=ON -DBUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX="/opt/dev/versions/vtk/vtk-7.1.0-shared" -DPYTHON_INCLUDE_DIR="/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/" -DPYTHON_LIBRARY="/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib"
    
    Run Code Online (Sandbox Code Playgroud)
  • 将 python 包安装在 python 可以找到的位置。就我而言,这是/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages 请注意,我需要DYLD_LIBRARY_PATH通过库所在的位置扩展/opt/dev/versions/vtk/vtk-7.1.0-shared/lib/.

  • 如果我从终端启动python,我可以成功导入vtk。

    import vtk
    v = vtk.vtkVersion()
    print v.GetVTKVersion()
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果我尝试在 PyCharm 的 python 控制台中导入 vtk,我会收到以下错误:

    Traceback (most recent call last):
      File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2881, in run_code
        exec(code_obj, self.user_global_ns, self.user_ns)
      File "<ipython-input-2-b7e11aadda62>", line 1, in <module>
        import vtk
      File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_import_hook.py", line 21, in do_import
        module = self._system_import(name, *args, **kwargs)
      File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/vtk/__init__.py", line 41, in <module>
        from .vtkCommonCore import *
      File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_import_hook.py", line 21, in do_import
        module = self._system_import(name, *args, **kwargs)
      File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/vtk/vtkCommonCore.py", line 9, in <module>
        from vtkCommonCorePython import *
      File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_import_hook.py", line 21, in do_import
        module = self._system_import(name, *args, **kwargs)
    ImportError: No module named vtkCommonCorePython
    
    Run Code Online (Sandbox Code Playgroud)

到目前为止,我了解到问题是由El Capitan 中引入的系统完整性保护(SIP)引起的。影响之一是子进程对其他资源的访问权限有限,而且最有可能的是,PyCharm 将 python 作为单独的进程执行。

我也知道 python 无法导入 vtk,因为它找不到 python 模块链接到的 dylib。我可以通过两种方式验证这一点:

  • DYLD_LIBRARY_PATH是空的。这是因为 python 在 PyCharm 中作为子进程运行:os.getenv('DYLD_LIBRARY_PATH')返回None
  • 当我将所有库复制/opt/dev/versions/vtk/vtk-7.1.0-shared/lib/到当前工作目录时,我可以导入模块

现在的问题是:显然,DYLD_LIBRARY_PATH不能在子进程中使用,因此自 El Capitan 以来根本不应再使用。那么,如何正确替换这种在 MacOS 10.11 之前运行良好的“链接黑客”。有没有办法继续使用DYLD_LIBRARY_PATH

禁用 SIP 不是一种选择。显然,将 dylib 复制到当前工作目录会有所帮助,但这对我来说是不可行的。然而,将库放在站点包位置(vtk)并没有帮助。

我很确定很多人一直依赖DYLD_LIBRARY_PATH-hack 并且现在正在与 SIP 的后果作斗争 - 这就是为什么我认为社区可能会从这个相当冗长的问题中受益。

nor*_*ius 4

经过长时间的斗争,我终于解决了最后一点问题。

通过为已安装二进制文件的RPATH运行路径相关库设置固定值,我的链接问题就消失了。

实现这一目标有不同的可能性。我想一种选择是使用install_name_tool. 对我来说,最简单的方法是使用适当的 CMake 标志构建 vtk。这是我对cmake, whereCMAKE_MACOSX_RPATHCMAKE_INSTALL_RPATHmake the Difference 的更新调用:

    cmake -G Ninja .. -DCMAKE_BUILD_TYPE=Release \
              -DVTK_WRAP_PYTHON=ON \
              -DBUILD_EXAMPLES=OFF \
              -DBUILD_SHARED_LIBS=ON \
              -DBUILD_TESTING=OFF \
              -DCMAKE_INSTALL_PREFIX="/opt/dev/versions/vtk/vtk-7.1.0-shared" \
              -DCMAKE_MACOSX_RPATH=ON \
              -DCMAKE_INSTALL_RPATH="/opt/dev/versions/vtk/vtk-7.1.0-shared/lib" \
              -DPYTHON_INCLUDE_DIR="/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/" \
              -DPYTHON_LIBRARY="/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib"
Run Code Online (Sandbox Code Playgroud)

在此处阅读有关 CMake 的 rpath 处理的更多信息。请注意otool -L vtkCommonCorePython.so(例如)仍将写入@rpath输出,但该值仍然是固定的。

@rpath/libvtkCommonCorePython27D-7.1.1.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libvtkWrappingPython27Core-7.1.1.dylib (compatibility version 0.0.0, current version 0.0.0)
/Library/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.0)
@rpath/libvtksys-7.1.1.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libvtkCommonCore-7.1.1.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)
Run Code Online (Sandbox Code Playgroud)