如何在构建时强制使用python wheel特定于平台?

时间:2017-07-17 17:30:47

标签: python setuptools setup.py python-wheel

我正在开发一个python2包,其中setup.py包含一些自定义安装命令。这些命令实际上构建了一些Rust代码并输出了一些移动到python包中的.dylib文件。

重要的一点是Rust代码在python包之外。

如果python包是纯python或特定于平台(如果它包含一些C扩展),则应该自动检测

setuptools。 在我的例子中,当我运行python setup.py bdist_wheel时,生成的轮子被标记为纯python轮:<package_name>-<version>-py2-none-any.whl。 这是有问题的,因为我需要在不同的平台上运行此代码,因此我需要为每个平台生成一个轮子。

在构建方向盘时,是否有办法强制构建特定于平台?

4 个答案:

答案 0 :(得分:13)

这是我通常从uwsgi

查看的代码

基本方法是:

setup.py

# ...

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 特定组件来获取fancier

答案 1 :(得分:3)

root_is_pure技巧和空的ext_modules技巧都不适合我,但是经过大量搜索后,我终于在'pip setup.py bdist_wheel' no longer builds forced non-pure wheels中找到了可行的解决方案

基本上,您可以在Distribution类中覆盖“ has_ext_modules”函数,并将distclass设置为指向该覆盖的类。到那时,setup.py将相信您具有二进制发行版,并将使用特定版本的python,ABI和当前体系结构创建一个转轮。根据{{​​3}}的建议:

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)

答案 2 :(得分:2)

模块setuptoolsdistutilswheel通过检查是否具有ext_modules来确定python发行版是否纯。

如果您自己构建外部模块,仍然可以在ext_modules中列出它,以便构建工具知道它的存在。诀窍是提供一个空的源列表,以便setuptoolsdistutils不会尝试构建它。例如,

setup(
    ...,
    ext_modules=[
        setuptools.Extension(
            name='your.external.module',
            sources=[]
        )
    ]
)

对我来说,此解决方案比修补bdist_wheel命令更好。原因是bdist_wheel在内部调用install命令,并且该命令再次检查ext_modules是否存在,以决定在purelib还是platlib安装之间进行。如果未列出外部模块,则最终会在转盘内的purelib子文件夹中安装lib。使用auditwheel repair时会导致问题,抱怨安装在purelib文件夹中的扩展名。

答案 3 :(得分:2)

您还可以通过指定--plat-name来指定/欺骗特定的平台名称:

python setup.py bdist_wheel --plat-name=manylinux1_x86_64