[英]How to force a python wheel to be platform specific when building it?
我正在开发一个 python2 包,其中
setup.py<\/code>包含一些自定义安装命令。
这些命令实际上构建了一些 Rust 代码并输出了一些移动到 python 包中的
.dylib<\/code>文件。
重要的一点是,Rust 代码在 python 包之外。
setuptools<\/code>应该自动检测 python 包是纯 python 还是特定于平台的(例如,如果它包含一些 C 扩展)。
就我而言,当我运行
python setup.py bdist_wheel<\/code> ,生成的轮子被标记为纯 python 轮子:
<package_name>-<version>-py2-none-any.whl<\/code> 。
这是有问题的,因为我需要在不同的平台上运行这段代码,因此我需要为每个平台生成一个轮子。
有没有办法在构建轮子时强制构建特定于平台?
下面是我平时从uwsgi看的代码
基本方法是:
# ...
try:
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
class bdist_wheel(_bdist_wheel):
def finalize_options(self):
_bdist_wheel.finalize_options(self)
self.root_is_pure = False
except ImportError:
bdist_wheel = None
setup(
# ...
cmdclass={'bdist_wheel': bdist_wheel},
)
root_is_pure
位告诉轮子机器构建一个非 purelib ( pyX-none-any
) 轮子。 您还可以得到票友说有二进制平台相关的组件,但没有CPython的ABI特定组件。
模块setuptools
、 distutils
和wheel
通过检查是否有ext_modules
决定 python 发行版是否纯。
如果您自己构建外部模块,您仍然可以将其列在ext_modules
以便构建工具知道它存在。 诀窍是提供一个空的源列表,这样setuptools
和distutils
就不会尝试构建它。 例如,
setup(
...,
ext_modules=[
setuptools.Extension(
name='your.external.module',
sources=[]
)
]
)
这个解决方案比修补bdist_wheel
命令更适合我。 原因是bdist_wheel
在内部调用install
命令,该命令再次检查ext_modules
的存在,以决定是安装purelib
还是platlib
。 如果您没有列出外部模块,您最终purelib
lib 安装在purelib
内的purelib
子文件夹中。 这会在使用auditwheel repair
时出现问题,它会抱怨扩展安装在purelib
文件夹中。
您还可以在构建轮子时通过指定--plat-name
来指定/欺骗特定的平台--plat-name
:
python setup.py bdist_wheel --plat-name=manylinux1_x86_64
root_is_pure 技巧和空的 ext_modules 技巧都对我不起作用,但经过我自己的大量搜索,我终于在“pip setup.py bdist_wheel”中找到了一个有效的解决方案, 不再构建强制非纯轮子
基本上,您覆盖 Distribution 类中的 'has_ext_modules' 函数,并将 distclass 设置为指向覆盖类。 那时,setup.py 会相信你有一个二进制发行版,并将创建一个带有特定版本的 python、ABI 和当前架构的轮子。 正如https://stackoverflow.com/users/5316090/py-j所建议的:
from setuptools import setup
from setuptools.dist import Distribution
DISTNAME = "packagename"
DESCRIPTION = ""
MAINTAINER = ""
MAINTAINER_EMAIL = ""
URL = ""
LICENSE = ""
DOWNLOAD_URL = ""
VERSION = '1.2'
PYTHON_VERSION = (2, 7)
# Tested with wheel v0.29.0
class BinaryDistribution(Distribution):
"""Distribution which always forces a binary package with platform name"""
def has_ext_modules(foo):
return True
setup(name=DISTNAME,
description=DESCRIPTION,
maintainer=MAINTAINER,
maintainer_email=MAINTAINER_EMAIL,
url=URL,
license=LICENSE,
download_url=DOWNLOAD_URL,
version=VERSION,
packages=["packagename"],
# Include pre-compiled extension
package_data={"packagename": ["_precompiled_extension.pyd"]},
distclass=BinaryDistribution)
我发现Anthony Sottile 的回答很棒,但对我没有用。
我的情况是我必须强制为 x86_64 创建轮子,但是任何 python3,所以使根不纯实际上导致我的轮子是 py36-cp36 :(
一个更好的方法,IMO,一般来说就是使用sys.argv
:
from setuptools import setup
import sys
sys.argv.extend(['--plat-name', 'x86_64'])
setup(name='example-wheel')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.