我对 Rtree 的问题感到困惑,Rtree 是我偶尔贡献的一个 Python 包。该包使用 cibuildwheel 为 PyPI 生成二进制轮子。该包使用 ctypes 绑定到 libspatialindex 的 C API。
以下是该过程的高级描述:
build.yml
install_libspatialindex.bash
进行编译,并且 *.so*
共享库被复制到 Rtree Python 包中(特别是 rtree/lib
)setup.py
控制,它将rtree/lib
文件复制到轮子。 (可能package-data
会更容易,但这是题外话)。这个初始的二进制轮是例如构建的python -m build --wheel
添加了 rtree/lib/libspatialindex.so
和 rtree/lib/libspatialindex_c.so
。patchelf
为二进制轮生成新的 Rtree.libs/libspatialindex-91fc2909.so.6.1.1
共享库。最终结果是一个带有两个共享库副本的 Linux 二进制轮(一个在
Rtree.libs
中,原始版本在 rtree/lib
中)。首选库是由 Auditwheel 创建的库,位于 Rtree.libs
。
解决方法可能是在
rtree/lib
和
wheel unpack
的帮助下删除
wheel pack
。
应该如何配置 cibuildwheel/auditwheel 来“发现”并使用与 ctypes 一起使用的外部库? (例如,上面的描述是“在包中捆绑二进制文件”方法)。这一挑战由审核轮限制之一描述,它无法静态确定库依赖关系,因为代码在运行时使用 ctypes 动态加载库。
对现代实践的指导将不胜感激。
使用 cibuildwheel 和auditwheel 构建 Python Wheel 时,有几种方法可以处理外部共享库依赖关系:
Bundled Libraries (current approach)
Bundle the required shared libraries directly in the package.
Copy them into the wheel during python setup.py bdist_wheel.
auditwheel will discover them and add to .libs folder.
Pointers to System Libraries
Compile with rpath pointing to standard system paths like /usr/lib.
auditwheel will discover the system libs and make the wheel self-contained.
Set rpath to Relative Path
Compile with rpath set to $ORIGIN/lib
auditwheel will rewrite the rpath to point inside the wheel.
Build Shared Library into Wheel
Add custom commands to build the shared lib during wheel building.
Configure auditwheel to insert library into .libs.
对于 Rtree,由于需要自定义 libspatialindex 构建,因此当前的捆绑方法是合理的。另一种选择是#4,将其直接构建到轮子中。
关键是要确保:
Libraries are discoverable by auditwheel
rpath points to bundled or standard system locations
auditwheel can resolve all dependencies
使用相对 rpath 或构建到wheel中有助于auditwheel“自包含”发行版。
噗。