如何跨平台打包依赖共享库的pybind11扩展Python模块?
跨平台打包pybind11扩展与依赖共享库方案
一、CMake构建阶段:统一共享库输出路径
修改现有CMake文件,将编译好的piper-phonemize扩展、onnxruntime和espeak-ng的共享库,统一输出到Python包目录下的子文件夹(比如src/piper_phonemize/libs):
# 设置库文件输出目录,匹配Python包结构 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/piper_phonemize/libs) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/piper_phonemize/libs) # Windows下DLL属于runtime类型
编译后所有依赖库会自动存入指定的包内目录,避免后续手动拷贝。
二、pyproject.toml配置:确保打包时包含共享库
在pyproject.toml中明确声明需要打包的平台专属库文件,防止打包过程遗漏:
[tool.setuptools.package-data] piper_phonemize = ["libs/*.dll", "libs/*.so", "libs/*.dylib"]
三、包初始化脚本:适配平台加载依赖
在Python包的__init__.py中添加平台适配逻辑,确保导入扩展前能找到依赖库:
import os import sys import ctypes # 获取包内libs目录的绝对路径 package_dir = os.path.dirname(__file__) libs_dir = os.path.join(package_dir, "libs") # 根据平台设置动态库搜索路径 if sys.platform.startswith("win"): os.environ["PATH"] = f"{libs_dir};{os.environ['PATH']}" elif sys.platform.startswith("linux"): os.environ["LD_LIBRARY_PATH"] = f"{libs_dir}:{os.environ.get('LD_LIBRARY_PATH', '')}" elif sys.platform == "darwin": os.environ["DYLD_LIBRARY_PATH"] = f"{libs_dir}:{os.environ.get('DYLD_LIBRARY_PATH', '')}" # 显式加载依赖库(提升跨平台兼容性) try: if sys.platform.startswith("win"): ctypes.CDLL(os.path.join(libs_dir, "espeak-ng.dll")) ctypes.CDLL(os.path.join(libs_dir, "onnxruntime.dll")) elif sys.platform.startswith("linux"): ctypes.CDLL(os.path.join(libs_dir, "libespeak-ng.so")) ctypes.CDLL(os.path.join(libs_dir, "libonnxruntime.so")) elif sys.platform == "darwin": ctypes.CDLL(os.path.join(libs_dir, "libespeak-ng.dylib")) ctypes.CDLL(os.path.join(libs_dir, "libonnxruntime.dylib")) except OSError as e: raise RuntimeError(f"加载依赖库失败: {e}") # 导入pybind11扩展 from .piper_phonemize import *
四、setup.py补充配置(可选)
如果仍需通过setup.py管理构建,同步添加package_data配置,与pyproject.toml保持一致:
from setuptools import setup, find_packages setup( name="piper-phonemize", packages=find_packages("src"), package_dir={"": "src"}, package_data={ "piper_phonemize": ["libs/*.dll", "libs/*.so", "libs/*.dylib"], }, # 其他构建配置... )
五、验证流程
- 用CMake编译所有库到指定的
libs目录 - 执行
python -m build生成wheel包,或直接pip install .安装 - 在干净的Python环境中测试导入:
import piper_phonemize,确认无加载错误
内容的提问来源于stack exchange,提问作者anonymous
相关产品推荐
相关产品推荐

