'pip setup.py bdist_wheel' no longer builds forced non-pure wheels

前端 未结 3 473
误落风尘
误落风尘 2020-12-06 17:59

I have a project that compiles with C extensions on Linux, but without them on Windows. When I first generated the wheel files on Windows with python setup.py bdist_wh

相关标签:
3条回答
  • 2020-12-06 18:27

    I've just run into this issue myself with Python v2.7 and wheel v0.29.0 on Windows 7 x64, where I build a Python package with some pre-compiled extensions (complicated VisualStudio setup with SWIG and external DLLs).

    After examining the source code I have found that overriding Distribution.has_ext_modules works (automatically includes platform name and ABI tag):

    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)
    
    0 讨论(0)
  • 2020-12-06 18:34

    The difference, of course, is in the environment, on the correctly working Win XP there is an older version of the wheel package installed (0.24.0) whereas on Appveyor the latest and greatest (and broken) version 0.26 of wheel gets installed (0.25 is broken as well).

    Changing the install stanza in the YAML file to fix the wheel version:

    install:
      - |
        %PYTHON%\python.exe -m pip install --upgrade pip
        %PYTHON%\python.exe -m pip install wheel==0.24
    

    is enough to get this to work quickly.

    You should however upgrade your the wheel package on your Linux box to version 0.28 and then use the new commandline option --plat-name:

    python setup.py sdist
    python2 setup.py bdist_wheel --plat-name win32
    python2 setup.py bdist_wheel --plat-name win_amd64
    python3 setup.py bdist_wheel --plat-name win32
    python3 setup.py bdist_wheel --plat-name win_amd64
    

    that will generate:

    pkg-1.1.tar.gz
    dist/pkg-1.1-py2-none-win32.whl
    dist/pkg-1.1-py2-none-win32.whl
    dist/pkg-1.1-py3-none-win_amd64.whl
    dist/pkg-1.1-py3-none-win32.whl
    dist/pkg-1.0-cp34-none-win_amd64.whl
    

    which you can upload to PyPI and results in the correct (.tar.gz) file downloading on Linux and the appropriate wheel on Windows. By just making sure that if the --plat-name win... is specified setup() is called with ext_modules=None. The resulting wheel files have minor (line endings in 3 files and their SHA256SUM), but install normally on Windows.

    That way you no longer need to build these packages, that are essentially pure packages, on a Windows machine

    For me this change by Nate Coraor brings my total build time down from 15+ minutes to about 7 seconds

    0 讨论(0)
  • 2020-12-06 18:47

    An alternative that seems to do the same as the accepted answer but more concisely is this:

    from setuptools import setup
    
    DISTNAME = "packagename"
    DESCRIPTION = ""
    MAINTAINER = ""
    MAINTAINER_EMAIL = ""
    URL = ""
    LICENSE = ""
    DOWNLOAD_URL = ""
    VERSION = '1.2'
    PYTHON_VERSION = (2, 7)
    
    
    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"]},
          has_ext_modules=lambda: True)
    
    0 讨论(0)
提交回复
热议问题