Search code examples
pythonsetuptoolspython-wheel

Wheel names are platform independent even though my package includes compiled libraries


I'm trying to generate platform specific binary distribution packages for windows, but python setup.py bdist_wheel generates universal file names. What do I need to change in my setup.py or otherwise to get wheels with platform specific names? From what I gather setuptools is supposed to recognize when a package will not be universal, but this is not working for me.

The project I'm working on compiles several variants of libraries using cmake and mingw w64. These compiled libraries are of course 32/64 bit specific. To create the individual distributions I create a virtualenv for the target platform from which I compile the libraries. The compiled libraries are then copied into the python package to be wheel'd.

Here is my setup.py. pyfvs_files is a list of compiled, '*.pyd' files to include. This produces wheels named 'pyfvs-0.0.1a0-py27-none-any.whl' where I would expect it to be 'pyfvs-0.0.1a0-py27-none-win32.whl' and 'pyfvs-0.0.1a0-py27-none-win_amd64.whl'. When installed via pip the packages function as expected for the target platform, but of course fail for the alternate platform. Ultimately I'd like to support Python 2.7, 3.4, 3.5 on both windows 32 & 64 bit and linux 64 bit.

import os
from glob import glob

from setuptools import setup
from setuptools.dist import Distribution

# TODO: Get the version from the git tag and or revision.
version = '0.0.1a0'

if os.name=='nt':
    so_ext = 'pyd'
else:
    so_ext = 'so'

pyfvs_files = glob('pyfvs/*.{}'.format(so_ext))
pyfvs_files.extend(['pyfvs/pyfvs.cfg',])

description = open('./README.txt').readline().strip()
long_desc = open('./README.txt').read().strip()

class BinaryDistribution(Distribution):
    def is_pure(self):
        return False

setup(
    name='pyfvs'
    , version=version
    , description=description
    , long_description=long_desc
    , url=''
    , author=""
    , author_email=""
    , packages=['pyfvs',]
    , include_package_data=True
    , distclass=BinaryDistribution
    , data_files = [
            ('pyfvs',pyfvs_files)
            , ('pyfvs/docs',glob('pyfvs/docs/*'))
            , ('pyfvs/examples',glob('pyfvs/examples/*'))
            , ('pyfvs/test',glob('pyfvs/test/*'))
            ]
    , entry_points={
            'console_scripts': [
            'fvs=pyfvs.__main__:main'
            ]
        }
    , classifiers=[
            'Development Status :: 3 - Alpha'
            , 'Environment :: Console'
            , 'Intended Audience :: Developers'
            , 'Intended Audience :: End Users/Desktop'
            , 'Intended Audience :: Science/Research'
            , 'Natural Language :: English'
            , 'Programming Language :: Python'
            , 'Programming Language :: Fortran'
            ]
    , keywords=''
    )

Solution

  • I've found no solution, but a workaround was to include a C extension in the setup, a small dummy library will suffice, as suggested here. Setuptools then knows the binary distributions are no longer platform independent and the resulting wheels, etc. are named appropriately. My solution was to go ahead and write a Cython extension to provide some useful functions to be integrated with my wrapper classes.

    Presumably subclassing Distribution and setting the is_pure=false is supposed accomplish the same thing, but it doesn't. I have not investigated this further.