cython
/
setup.py
356 строк · 13.1 Кб
1#!/usr/bin/env python
2try:3from setuptools import setup, Extension4except ImportError:5from distutils.core import setup, Extension6import os7import stat8import subprocess9import textwrap10import sys11
12import platform13is_cpython = platform.python_implementation() == 'CPython'14
15# this specifies which versions of python we support, pip >= 9 knows to skip
16# versions of packages which are not compatible with the running python
17PYTHON_REQUIRES = '>=3.7'18
19if sys.platform == "darwin":20# Don't create resource files on OS X tar.21os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'22os.environ['COPYFILE_DISABLE'] = 'true'23
24setup_args = {}25
26def add_command_class(name, cls):27cmdclasses = setup_args.get('cmdclass', {})28cmdclasses[name] = cls29setup_args['cmdclass'] = cmdclasses30
31from distutils.command.sdist import sdist as sdist_orig32class sdist(sdist_orig):33def run(self):34self.force_manifest = 135if (sys.platform != "win32" and36os.path.isdir('.git')):37assert os.system("git rev-parse --verify HEAD > .gitrev") == 038sdist_orig.run(self)39add_command_class('sdist', sdist)40
41pxd_include_dirs = [42directory for directory, dirs, files43in os.walk(os.path.join('Cython', 'Includes'))44if '__init__.pyx' in files or '__init__.pxd' in files45or directory == os.path.join('Cython', 'Includes')]46
47pxd_include_patterns = [48p+'/*.pxd' for p in pxd_include_dirs ] + [49p+'/*.pyx' for p in pxd_include_dirs ]50
51setup_args['package_data'] = {52'Cython.Plex' : ['*.pxd'],53'Cython.Compiler' : ['*.pxd'],54'Cython.Runtime' : ['*.pyx', '*.pxd'],55'Cython.Utility' : ['*.pyx', '*.pxd', '*.c', '*.h', '*.cpp'],56'Cython' : [ p[7:] for p in pxd_include_patterns ] + ['py.typed', '__init__.pyi', 'Shadow.pyi'],57'Cython.Debugger.Tests': ['codefile', 'cfuncs.c'],58}
59
60# This dict is used for passing extra arguments that are setuptools
61# specific to setup
62setuptools_extra_args = {}63
64if 'setuptools' in sys.modules:65setuptools_extra_args['python_requires'] = PYTHON_REQUIRES66setuptools_extra_args['zip_safe'] = False67setuptools_extra_args['entry_points'] = {68'console_scripts': [69'cython = Cython.Compiler.Main:setuptools_main',70'cythonize = Cython.Build.Cythonize:main',71'cygdb = Cython.Debugger.Cygdb:main',72]73}74scripts = []75else:76if os.name == "posix":77scripts = ["bin/cython", "bin/cythonize", "bin/cygdb"]78else:79scripts = ["cython.py", "cythonize.py", "cygdb.py"]80
81
82def compile_cython_modules(profile=False, coverage=False, compile_minimal=False, compile_more=False, cython_with_refnanny=False,83cython_limited_api=False):84source_root = os.path.abspath(os.path.dirname(__file__))85compiled_modules = [86"Cython.Plex.Actions",87"Cython.Plex.Scanners",88"Cython.Compiler.FlowControl",89"Cython.Compiler.LineTable",90"Cython.Compiler.Scanning",91"Cython.Compiler.Visitor",92"Cython.Runtime.refnanny",93]94if not compile_minimal:95compiled_modules.extend([96"Cython.Plex.Machines",97"Cython.Plex.Transitions",98"Cython.Plex.DFA",99"Cython.Compiler.Code",100"Cython.Compiler.FusedNode",101"Cython.Compiler.Parsing",102"Cython.Tempita._tempita",103"Cython.StringIOTree",104"Cython.Utils",105])106if compile_more and not compile_minimal:107compiled_modules.extend([108"Cython.Compiler.Lexicon",109"Cython.Compiler.Pythran",110"Cython.Build.Dependencies",111"Cython.Compiler.ParseTreeTransforms",112"Cython.Compiler.Nodes",113"Cython.Compiler.ExprNodes",114"Cython.Compiler.ModuleNode",115"Cython.Compiler.Optimize",116])117
118from distutils.spawn import find_executable119from distutils.sysconfig import get_python_inc120pgen = find_executable(121'pgen', os.pathsep.join([os.environ['PATH'], os.path.join(get_python_inc(), '..', 'Parser')]))122if not pgen:123sys.stderr.write("Unable to find pgen, not compiling formal grammar.\n")124else:125parser_dir = os.path.join(os.path.dirname(__file__), 'Cython', 'Parser')126grammar = os.path.join(parser_dir, 'Grammar')127subprocess.check_call([128pgen,129os.path.join(grammar),130os.path.join(parser_dir, 'graminit.h'),131os.path.join(parser_dir, 'graminit.c'),132])133cst_pyx = os.path.join(parser_dir, 'ConcreteSyntaxTree.pyx')134if os.stat(grammar)[stat.ST_MTIME] > os.stat(cst_pyx)[stat.ST_MTIME]:135mtime = os.stat(grammar)[stat.ST_MTIME]136os.utime(cst_pyx, (mtime, mtime))137compiled_modules.extend([138"Cython.Parser.ConcreteSyntaxTree",139])140
141defines = []142extra_extension_args = {}143if cython_limited_api:144defines += [145('Py_LIMITED_API', '0x03070000'),146]147extra_extension_args['py_limited_api'] = True148
149if cython_with_refnanny:150defines.append(('CYTHON_REFNANNY', '1'))151if coverage:152defines.append(('CYTHON_TRACE', '1'))153
154extensions = []155for module in compiled_modules:156source_file = os.path.join(source_root, *module.split('.'))157pyx_source_file = source_file + ".py"158if not os.path.exists(pyx_source_file):159pyx_source_file += "x" # .py -> .pyx160
161dep_files = []162if os.path.exists(source_file + '.pxd'):163dep_files.append(source_file + '.pxd')164
165# Note that refnanny does not currently support being build in the limited API.166# This should eventually change when cpython is cimportable.167extensions.append(Extension(168module, sources=[pyx_source_file],169define_macros=defines if '.refnanny' not in module else [],170depends=dep_files,171**(extra_extension_args if '.refnanny' not in module else {})))172# XXX hack around setuptools quirk for '*.pyx' sources173extensions[-1].sources[0] = pyx_source_file174
175# optimise build parallelism by starting with the largest modules176extensions.sort(key=lambda ext: os.path.getsize(ext.sources[0]), reverse=True)177
178from Cython.Distutils.build_ext import build_ext as cy_build_ext179build_ext = None180try:181# Use the setuptools build_ext in preference, because it182# gets limited api filenames right, and should inherit itself from183# Cython's own build_ext. But failing that, use the Cython build_ext184# directly.185from setuptools.command.build_ext import build_ext186if cy_build_ext not in build_ext.__mro__:187build_ext = cy_build_ext188except ImportError:189build_ext = cy_build_ext190
191from Cython.Compiler.Options import get_directive_defaults192get_directive_defaults().update(193language_level=3,194auto_pickle=False,195binding=False,196always_allow_keywords=False,197autotestdict=False,198)199if profile:200get_directive_defaults()['profile'] = True201sys.stderr.write("Enabled profiling for the Cython binary modules\n")202if coverage:203get_directive_defaults()['linetrace'] = True204sys.stderr.write("Enabled line tracing and profiling for the Cython binary modules\n")205
206# not using cythonize() directly to let distutils decide whether building extensions was requested207add_command_class("build_ext", build_ext)208setup_args['ext_modules'] = extensions209
210
211def check_option(name):212cli_arg = "--" + name213if cli_arg in sys.argv:214sys.argv.remove(cli_arg)215return True216
217env_var = name.replace("-", "_").upper()218if os.environ.get(env_var) == "true":219return True220
221return False222
223
224cython_profile = check_option('cython-profile')225cython_coverage = check_option('cython-coverage')226cython_with_refnanny = check_option('cython-with-refnanny')227
228compile_cython_itself = not check_option('no-cython-compile')229if compile_cython_itself:230cython_compile_more = check_option('cython-compile-all')231cython_compile_minimal = check_option('cython-compile-minimal')232cython_limited_api = check_option('cython-limited-api')233# TODO - enable this when refnanny can be compiled234if cython_limited_api and False:235setup_options = setup_args.setdefault('options', {})236bdist_wheel_options = setup_options.setdefault('bdist_wheel', {})237bdist_wheel_options['py_limited_api'] = 'cp37'238
239
240setup_args.update(setuptools_extra_args)241
242
243def dev_status(version: str):244if 'b' in version or 'c' in version:245# 1b1, 1beta1, 2rc1, ...246return 'Development Status :: 4 - Beta'247elif 'a' in version:248# 1a1, 1alpha1, ...249return 'Development Status :: 3 - Alpha'250else:251return 'Development Status :: 5 - Production/Stable'252
253
254packages = [255'Cython',256'Cython.Build',257'Cython.Compiler',258'Cython.Runtime',259'Cython.Distutils',260'Cython.Debugger',261'Cython.Debugger.Tests',262'Cython.Plex',263'Cython.Tests',264'Cython.Build.Tests',265'Cython.Compiler.Tests',266'Cython.Utility',267'Cython.Tempita',268'pyximport',269]
270
271
272def run_build():273if compile_cython_itself and (is_cpython or cython_compile_more or cython_compile_minimal):274compile_cython_modules(cython_profile, cython_coverage, cython_compile_minimal, cython_compile_more, cython_with_refnanny,275cython_limited_api)276
277from Cython import __version__ as version278setup(279name='Cython',280version=version,281url='https://cython.org/',282author='Robert Bradshaw, Stefan Behnel, David Woods, Greg Ewing, et al.',283author_email='cython-devel@python.org',284description="The Cython compiler for writing C extensions in the Python language.",285long_description=textwrap.dedent("""\286The Cython language makes writing C extensions for the Python language as
287easy as Python itself. Cython is a source code translator based on Pyrex_,
288but supports more cutting edge functionality and optimizations.
289
290The Cython language is a superset of the Python language (almost all Python
291code is also valid Cython code), but Cython additionally supports optional
292static typing to natively call C functions, operate with C++ classes and
293declare fast C types on variables and class attributes. This allows the
294compiler to generate very efficient C code from Cython code.
295
296This makes Cython the ideal language for writing glue code for external
297C/C++ libraries, and for fast C modules that speed up the execution of
298Python code.
299
300The newest Cython release can always be downloaded from https://cython.org/.
301Unpack the tarball or zip file, enter the directory, and then run::
302
303pip install .
304
305Note that for one-time builds, e.g. for CI/testing, on platforms that are not
306covered by one of the wheel packages provided on PyPI *and* the pure Python wheel
307that we provide is not used, it is substantially faster than a full source build
308to install an uncompiled (slower) version of Cython with::
309
310NO_CYTHON_COMPILE=true pip install .
311
312.. _Pyrex: https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
313"""),314license='Apache-2.0',315classifiers=[316dev_status(version),317"Intended Audience :: Developers",318"License :: OSI Approved :: Apache Software License",319"Operating System :: OS Independent",320"Programming Language :: Python",321"Programming Language :: Python :: 3",322"Programming Language :: Python :: 3.7",323"Programming Language :: Python :: 3.8",324"Programming Language :: Python :: 3.9",325"Programming Language :: Python :: 3.10",326"Programming Language :: Python :: 3.11",327"Programming Language :: Python :: 3.12",328"Programming Language :: Python :: 3.13",329"Programming Language :: Python :: Implementation :: CPython",330"Programming Language :: Python :: Implementation :: PyPy",331"Programming Language :: Python :: Implementation :: Stackless",332"Programming Language :: C",333"Programming Language :: C++",334"Programming Language :: Cython",335"Topic :: Software Development :: Code Generators",336"Topic :: Software Development :: Compilers",337"Topic :: Software Development :: Libraries :: Python Modules",338"Typing :: Typed"339],340project_urls={341"Documentation": "https://cython.readthedocs.io/",342"Donate": "https://cython.readthedocs.io/en/latest/src/donating.html",343"Source Code": "https://github.com/cython/cython",344"Bug Tracker": "https://github.com/cython/cython/issues",345"User Group": "https://groups.google.com/g/cython-users",346},347
348scripts=scripts,349packages=packages,350py_modules=["cython"],351**setup_args352)353
354
355if __name__ == '__main__':356run_build()357