I have a question. I would like to distribute my packages based on cython, but I do not see an easy way to create them in the setup.py file. I would like to setup.py for:
- Most important: install my package without cython (from pre-generated C files or by installing cython in advance)
- rebuild (run cythonize) package on sdist
- don't need a list of hard codes of my cython modules (just use glob or something else)
- be able to work without .c files (should not be stored in git) or .pyx (may not be distributed). at least one of these sets will always be present, of course.
Currently, in my buttock package I use this rather complex code:
import os
from glob import glob
from distutils.command.build_ext import build_ext as _build_ext
from distutils.command.sdist import sdist as _sdist
from distutils.core import setup
from distutils.core import Extension
def generate_extensions():
return [
Extension(os.path.splitext(name)[0], [name])
for name in C_FILES
]
CYTHON_FILES = glob('itchy/*.pyx')
C_FILES = glob('itchy/*.c')
extensions = generate_extensions()
class build_ext(_build_ext):
def run(self):
try:
from Cython.Build import cythonize
if CYTHON_FILES:
cythonize(CYTHON_FILES)
global C_FILES, extensions
C_FILES = glob('itchy/*.c')
extensions = generate_extensions()
else:
print('No .pyx files found, building extensions skipped. Pre-built versions will be used.')
except ImportError:
print('Cython is not installed, building extensions skipped. Pre-built versions will be used.')
assert C_FILES, 'C files have to be present in distribution or Cython has to be installed'
_build_ext.run(self)
class sdist(_sdist):
def run(self):
self.run_command("build_ext")
_sdist.run(self)
setup(
(...)
ext_modules = extensions,
cmdclass = {
'build_ext': build_ext,
'sdist': sdist,
},
)