如何用C++构建Python扩展并将依赖.so文件纳入Wheel包
把pybind11绑定依赖的共享库打包进Wheel的实现方案
1. 编译绑定库时设置相对RPATH
编译lib_bindings_ab.so时,添加链接器参数,让它优先在自身所在目录查找lib_a.so和lib_b.so,无需依赖系统路径:
- 用CMake构建的话,添加配置:
set_target_properties(lib_bindings_ab PROPERTIES BUILD_WITH_INSTALL_RPATH ON INSTALL_RPATH "$ORIGIN" ) - 直接用g++编译的话:
g++ -shared -fPIC bindings.cpp -o lib_bindings_ab.so -L./path/to/libs -l_a -l_b -Wl,-rpath='$ORIGIN'
2. 调整项目目录结构
将所有.so文件放到Python包的子目录中,示例结构:
my_pybind_project/ ├── my_package/ │ ├── __init__.py │ └── native_libs/ │ ├── lib_a.so │ ├── lib_b.so │ └── lib_bindings_ab.so └── setup.py
在__init__.py中完成库的导入逻辑:
import os import sys from ctypes import CDLL # 获取native_libs目录的绝对路径 lib_dir = os.path.join(os.path.dirname(__file__), "native_libs") # 预加载依赖库(RPATH配置正确时可省略,添加更稳妥) CDLL(os.path.join(lib_dir, "lib_a.so")) CDLL(os.path.join(lib_dir, "lib_b.so")) # 将库目录加入系统路径,导入绑定库 sys.path.insert(0, lib_dir) from lib_bindings_ab import * # 替换为你的绑定库导出内容
3. 配置setup.py打包规则
用setuptools确保所有.so文件被包含进Wheel:
from setuptools import setup, find_packages setup( name="my_package", version="0.1.0", packages=find_packages(), package_data={ "my_package": ["native_libs/*.so"] } )
4. 构建与验证Wheel
- 构建Wheel包:
pip install wheel python setup.py bdist_wheel - 验证内容:解压生成的
.whl文件,检查my_package/native_libs/下是否包含所有三个.so文件。 - 测试安装:在干净环境中执行
pip install 生成的wheel文件名,导入包验证功能正常。
额外注意事项
- Linux平台建议用
auditwheel处理Wheel,提升跨发行版兼容性:
修复后的Wheel存放在pip install auditwheel auditwheel repair dist/my_package-0.1.0-cp310-cp310-linux_x86_64.whlfixed/目录中。 - 不同平台(Linux、macOS、Windows)的.so/.dylib/.dll文件需分开构建,发布对应平台的Wheel。
- 若绑定库依赖系统级第三方库(如OpenCV、Boost),仍需用户提前安装,但自定义的
lib_a.so/lib_b.so可正常打包。
内容的提问来源于stack exchange,提问作者tenspd137
相关产品推荐
相关产品推荐

