eth*_*oks 5 portability distutils dylib cython
python setup.py bdist_wheel在使用或等效命令构建 Cython 模块后,我需要运行某些命令。这可能吗?
具体情况如下:\n我正在为 osx 开发 Cython 程序。它链接到.dylib我的主目录中的某些文件,并且要构建程序,您必须运行
export DYLD_LIBRARY_PATH=/path/to/parent/dir\nRun Code Online (Sandbox Code Playgroud)\n\n(这很麻烦)或包含一个指令来setup.py运行
install_name_tool -change @executable_path/my.dylib /path/to/my.dylib\nRun Code Online (Sandbox Code Playgroud)\n\n这基本上的作用是告诉二进制文件在哪里寻找dylib. 这两种选择都不是理想的,但后者似乎更便携。现在我刚刚将这些说明添加到 的底部setup.py,但这仍然不可移植:假设我按如下方式打包并上传我的包:
python setup.py sdist # I think this collects source files into a .tar\npython setup.py bdist_wheel # I think this builds a binary. This is where I assume the post-compilation stuff should happen.\ntwine upload dist/* # This puts stuff up on PyPi.\nRun Code Online (Sandbox Code Playgroud)\n\n现在,我已经阅读了文档和一些教程,但我承认我仍然不能 100% 确定这些命令的作用。但我知道如果随后在另一个项目中我运行
\n\npip install mypackage\nRun Code Online (Sandbox Code Playgroud)\n\ndylib 问题浮出水面:
\n\nImportError: dlopen(/path/to/my/module.cpython-36m-darwin.so, 2): \nLibrary not loaded: @executable_path/my.dylib\n Referenced from: /path/to/my/module.cpython-36m-darwin.so\n Reason: image not found\nRun Code Online (Sandbox Code Playgroud)\n\n解决方案似乎是在 setup.py 中添加某种自动后编译指示以指示install_name_tool需要执行的操作。假设这是可能的,人们会怎么做呢?理想情况下,我想使用现成的Cython.Build.cythonize和setuptools.Extension,但也许我需要做一些更定制的事情。感谢您的建议!
Danny 正确地指出,运行install_name_tool不是一个可移植的解决方案,相反 dylib 应该以某种方式包含在包中。delocate是完成这项工作的工具,但我遇到的第一个挑战是它delocate不适用于@executable_path:
\xe2\x9d\xaf delocate-wheel -w fixed_wheels -v dist/*.whl\nFixing: dist/my-package-1.0.9-cp36-cp36m-macosx_10_12_x86_64.whl\n/Users/ethan/virtualenvs/my-package/lib/python3.6/site-packages/delocate/delocating.py:71: UserWarning: Not processing required path @executable_path/my.dylib because it begins with @\n \'begins with @\'.format(required))\nRun Code Online (Sandbox Code Playgroud)\n\n使用otool,我能够验证 ofid的my.dylib用途@executable_path:
\xe2\x9d\xaf otool -L my.dylib\nmy.dylib:\n @executable_path/my.dylib (compatibility version 0.0.0, current version 0.0.0)\n /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)\n /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)\n /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)\n /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1258.1.0)\n /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)\nRun Code Online (Sandbox Code Playgroud)\n\n为了摆脱@executable_path我运行了以下命令:
\xe2\x9d\xaf install_name_tool -id my.dylib my.dylib\nRun Code Online (Sandbox Code Playgroud)\n\n现在看一下输出otool -L:
\xe2\x9d\xaf otool -L my.dylib\nmy.dylib:\n my.dylib (compatibility version 0.0.0, current version 0.0.0)\n /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)\n /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)\n /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)\n /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1258.1.0)\n /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)\nRun Code Online (Sandbox Code Playgroud)\n\n一般来说,这对于 dylib 来说不太好用id,但足以使用delocate-wheel。我重建了我的.whl:
python setup.py bdist_wheel\nRun Code Online (Sandbox Code Playgroud)\n\n现在当我跑步时delocate_wheel:
\xe2\x9d\xaf delocate-wheel -w fixed_wheels -v dist/*.whl\nFixing: dist/my.whl\nTraceback (most recent call last):\n... \ndelocate.delocating.DelocationError: library "/Users/ethan/my-package/my.dylib" does not exist\nRun Code Online (Sandbox Code Playgroud)\n\n这清楚地告诉我们delocate期望在哪里找到my.dylib。所以我复制my.dylib并/Users/ethan/my-package/my.dylib重新运行命令:
\xe2\x9d\xaf delocate-wheel -w fixed_wheels -v dist/*.whl\nFixing: dist/my.whl\nCopied to package .dylibs directory:\n /Users/ethan/my-package/my.dylib\nRun Code Online (Sandbox Code Playgroud)\n\n成功!.dylibs这个目录是什么?我跑去tar -xvf my.whl打开轮子的包装并检查里面的东西:
\xe2\x9d\xaf tree -a fixed_wheels/my-package\nfixed_wheels/my-package\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .dylibs\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 my.dylib\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.cpython-36m-darwin.so\nRun Code Online (Sandbox Code Playgroud)\n\n如您所见,my.dylib已将其复制到.dylibs/打包在my.whl. 上传my.whl到 pypi 后,我可以很好地下载并运行代码。
看看delocate和 Linux 等效的auditwheel。
分配工具无需在运行时更改链接加载器路径,而是将第三方库嵌入到轮子中并相应地调整加载时间路径。
结果是一个可分发的二进制轮,其中正确包含了所有依赖库。
设置运行时加载路径不可移植,并且无法跨 python 版本或机器体系结构工作。
例如,对于上面的例子,通过运行创建轮子后python setup.py bdist_wheel:
delocate-wheel -w fixed_wheels <wheel file>
目录下将放置一个固定的轮子文件fixed_wheels。运行-v看看它嵌入了哪些库。