How to force a python wheel to be platform specific when building it?

后端 未结 4 1844
南旧
南旧 2020-11-29 07:31

I am working on a python2 package in which the setup.py contains some custom install commands. These commands actually build some Rust code and output some

相关标签:
4条回答
  • 2020-11-29 08:07

    You can also specify/spoof a specific platform name when building wheels by specifying a --plat-name:

    python setup.py bdist_wheel --plat-name=manylinux1_x86_64
    
    0 讨论(0)
  • 2020-11-29 08:18

    Neither the root_is_pure trick nor the empty ext_modules trick worked for me, but after MUCH searching myself, I finally found a working solution in 'pip setup.py bdist_wheel' no longer builds forced non-pure wheels

    Basically, you override the 'has_ext_modules' function in the Distribution class, and set distclass to point to the overriding class. At that point, setup.py will believe you have a binary distribution, and will create a wheel with the specific version of python, the ABI, and the current architecture. As suggested by 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)
    
    0 讨论(0)
  • 2020-11-29 08:20

    Here's the code that I usually look at from uwsgi

    The basic approach is:

    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},
    )
    

    The root_is_pure bit tells the wheel machinery to build a non-purelib (pyX-none-any) wheel. You can also get fancier by saying there are binary platform-specific components but no cpython abi specific components.

    0 讨论(0)
  • 2020-11-29 08:20

    The modules setuptools, distutils and wheel decide whether a python distribution is pure by checking if it has ext_modules.

    If you build an external module on your own, you can still list it in ext_modules so that the building tools know it exists. The trick is to provide an empty list of sources so that setuptools and distutils will not try to build it. For example,

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

    This solution worked better for me than patching the bdist_wheel command. The reason is that bdist_wheel calls the install command internally and that command checks again for the existence of ext_modules to decide between purelib or platlib install. If you don't list the external module, you end up with the lib installed in a purelib subfolder inside the wheel. That causes problems when using auditwheel repair, which complains about the extensions being installed in a purelib folder.

    0 讨论(0)
提交回复
热议问题