如何使用Poetry构建适配多操作系统与架构的Python wheel包
核心结论
- Poetry 完全可以实现多平台专属 wheel 构建,不需要必须改用
setup.py。 - 你之前构建输出
py3-none-any.whl通用包的核心原因,是没有向构建系统声明包的平台相关性,Poetry 默认会将未检测到原生扩展、未引入平台专属文件的包判定为跨平台纯 Python 包,因此输出通用 wheel。
Poetry 配置方案
Poetry 基于 PEP 517 标准实现构建逻辑,1.2 及以上版本已经完整支持平台专属 wheel 打包,配置步骤如下:
- 调整
pyproject.toml的包文件规则
保留原有项目基础配置(name、version、authors 等),删除可能存在的pure = true配置(该配置会强制输出通用 wheel),添加平台专属文件的打包规则,将预编译好的各平台共享库按对应平台标记纳入打包范围:[tool.poetry] name = "your-package-name" version = "0.1.0" # 声明自身Python源码包的路径 packages = [{ include = "your_pkg_dir" }] # 关键:按平台标记预编译共享库的打包规则 include = [ { path = "native_libs/win_amd64/*.dll", format = "wheel", platform = "win_amd64" }, { path = "native_libs/win_arm64/*.dll", format = "wheel", platform = "win_arm64" }, { path = "native_libs/macos_x86_64/*.dylib", format = "wheel", platform = "macosx_10_9_x86_64" }, { path = "native_libs/macos_arm64/*.dylib", format = "wheel", platform = "macosx_11_0_arm64" }, { path = "native_libs/linux_x86_64/*.so", format = "wheel", platform = "manylinux2014_x86_64" }, { path = "native_libs/linux_aarch64/*.so", format = "wheel", platform = "manylinux2014_aarch64" }, ] [build-system] requires = ["poetry-core>=1.7.0"] build-backend = "poetry.core.masonry.api" - 分平台执行构建
Poetry 无法在单一系统环境下一次性交叉编译输出所有平台的 wheel,你需要在对应架构/系统的构建环境中(可以是本地对应系统的机器,也可以是 CI 的多矩阵任务),提前放入对应平台的预编译共享库,直接执行构建命令:
构建完成后会在poetry build --format wheeldist目录下生成对应平台 tag 的 wheel 包,例如your_package-0.1.0-py3-none-win_amd64.whl,不会再输出通用包。如果需要微调 wheel 的平台 tag,可以构建完成后用wheel tags命令修改,注意必须保证 tag 和包内二进制文件的实际架构匹配。
setuptools(setup.py)配置方案
如果你更习惯 setuptools 的构建逻辑,也可以通过 setup.py 实现相同的打包效果,核心逻辑同样是声明包非纯 Python、按平台引入预编译共享库:
- 编写
setup.py配置文件,示例如下:from setuptools import setup, find_packages from pathlib import Path import platform # 匹配当前构建环境对应的预编译共享库 def get_platform_native_libs(): sys_name = platform.system() arch = platform.machine() path_map = { ("Windows", "AMD64"): "native_libs/win_amd64/*.dll", ("Windows", "ARM64"): "native_libs/win_arm64/*.dll", ("Darwin", "x86_64"): "native_libs/macos_x86_64/*.dylib", ("Darwin", "arm64"): "native_libs/macos_arm64/*.dylib", ("Linux", "x86_64"): "native_libs/linux_x86_64/*.so", ("Linux", "aarch64"): "native_libs/linux_aarch64/*.so", } lib_pattern = path_map.get((sys_name, arch)) if not lib_pattern: raise RuntimeError(f"Unsupported build platform: {sys_name} {arch}") return [str(p.relative_to("your_pkg_dir")) for p in Path().glob(lib_pattern)] setup( name="your-package-name", version="0.1.0", packages=find_packages(), # 关键:声明包包含原生模块,不是纯Python通用包 has_ext_modules=lambda: True, # 将对应平台的共享库作为包数据打包 package_data={"your_pkg_dir": get_platform_native_libs()}, zip_safe=False, ) - 在对应平台的构建环境中安装构建依赖,执行构建命令:
同样会在pip install build wheel python -m build --wheeldist目录生成对应平台 tag 的 wheel 包。
注意事项
- 两种构建方式都无法在单一环境下输出全平台 wheel,多平台构建建议搭配 CI 多矩阵任务实现,每个任务运行对应架构的系统、提前准备好对应版本的预编译共享库即可。
- 禁止手动修改通用 wheel 的平台标签冒充平台专属包,会导致用户安装后出现二进制加载失败、架构不匹配的问题。
- 构建完成后可以直接解压 wheel 包检查内部文件,确认对应平台的共享库已经被正确打包后再发布。
内容的提问来源于stack exchange,提问作者Ordoshsen
相关产品推荐
相关产品推荐

