cython

Форк
0
/
setup.py 
356 строк · 13.1 Кб
1
#!/usr/bin/env python
2
try:
3
    from setuptools import setup, Extension
4
except ImportError:
5
    from distutils.core import setup, Extension
6
import os
7
import stat
8
import subprocess
9
import textwrap
10
import sys
11

12
import platform
13
is_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
17
PYTHON_REQUIRES = '>=3.7'
18

19
if sys.platform == "darwin":
20
    # Don't create resource files on OS X tar.
21
    os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
22
    os.environ['COPYFILE_DISABLE'] = 'true'
23

24
setup_args = {}
25

26
def add_command_class(name, cls):
27
    cmdclasses = setup_args.get('cmdclass', {})
28
    cmdclasses[name] = cls
29
    setup_args['cmdclass'] = cmdclasses
30

31
from distutils.command.sdist import sdist as sdist_orig
32
class sdist(sdist_orig):
33
    def run(self):
34
        self.force_manifest = 1
35
        if (sys.platform != "win32" and
36
            os.path.isdir('.git')):
37
            assert os.system("git rev-parse --verify HEAD > .gitrev") == 0
38
        sdist_orig.run(self)
39
add_command_class('sdist', sdist)
40

41
pxd_include_dirs = [
42
    directory for directory, dirs, files
43
    in os.walk(os.path.join('Cython', 'Includes'))
44
    if '__init__.pyx' in files or '__init__.pxd' in files
45
    or directory == os.path.join('Cython', 'Includes')]
46

47
pxd_include_patterns = [
48
    p+'/*.pxd' for p in pxd_include_dirs ] + [
49
    p+'/*.pyx' for p in pxd_include_dirs ]
50

51
setup_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
62
setuptools_extra_args = {}
63

64
if 'setuptools' in sys.modules:
65
    setuptools_extra_args['python_requires'] = PYTHON_REQUIRES
66
    setuptools_extra_args['zip_safe'] = False
67
    setuptools_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
    }
74
    scripts = []
75
else:
76
    if os.name == "posix":
77
        scripts = ["bin/cython", "bin/cythonize", "bin/cygdb"]
78
    else:
79
        scripts = ["cython.py", "cythonize.py", "cygdb.py"]
80

81

82
def compile_cython_modules(profile=False, coverage=False, compile_minimal=False, compile_more=False, cython_with_refnanny=False,
83
                           cython_limited_api=False):
84
    source_root = os.path.abspath(os.path.dirname(__file__))
85
    compiled_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
    ]
94
    if not compile_minimal:
95
        compiled_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
        ])
106
    if compile_more and not compile_minimal:
107
        compiled_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

118
    from distutils.spawn import find_executable
119
    from distutils.sysconfig import get_python_inc
120
    pgen = find_executable(
121
        'pgen', os.pathsep.join([os.environ['PATH'], os.path.join(get_python_inc(), '..', 'Parser')]))
122
    if not pgen:
123
        sys.stderr.write("Unable to find pgen, not compiling formal grammar.\n")
124
    else:
125
        parser_dir = os.path.join(os.path.dirname(__file__), 'Cython', 'Parser')
126
        grammar = os.path.join(parser_dir, 'Grammar')
127
        subprocess.check_call([
128
            pgen,
129
            os.path.join(grammar),
130
            os.path.join(parser_dir, 'graminit.h'),
131
            os.path.join(parser_dir, 'graminit.c'),
132
            ])
133
        cst_pyx = os.path.join(parser_dir, 'ConcreteSyntaxTree.pyx')
134
        if os.stat(grammar)[stat.ST_MTIME] > os.stat(cst_pyx)[stat.ST_MTIME]:
135
            mtime = os.stat(grammar)[stat.ST_MTIME]
136
            os.utime(cst_pyx, (mtime, mtime))
137
        compiled_modules.extend([
138
                "Cython.Parser.ConcreteSyntaxTree",
139
            ])
140

141
    defines = []
142
    extra_extension_args = {}
143
    if cython_limited_api:
144
        defines += [
145
            ('Py_LIMITED_API', '0x03070000'),
146
        ]
147
        extra_extension_args['py_limited_api'] = True
148

149
    if cython_with_refnanny:
150
        defines.append(('CYTHON_REFNANNY', '1'))
151
    if coverage:
152
        defines.append(('CYTHON_TRACE', '1'))
153

154
    extensions = []
155
    for module in compiled_modules:
156
        source_file = os.path.join(source_root, *module.split('.'))
157
        pyx_source_file = source_file + ".py"
158
        if not os.path.exists(pyx_source_file):
159
            pyx_source_file += "x"  # .py -> .pyx
160

161
        dep_files = []
162
        if os.path.exists(source_file + '.pxd'):
163
            dep_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.
167
        extensions.append(Extension(
168
            module, sources=[pyx_source_file],
169
            define_macros=defines if '.refnanny' not in module else [],
170
            depends=dep_files,
171
            **(extra_extension_args if '.refnanny' not in module else {})))
172
        # XXX hack around setuptools quirk for '*.pyx' sources
173
        extensions[-1].sources[0] = pyx_source_file
174

175
    # optimise build parallelism by starting with the largest modules
176
    extensions.sort(key=lambda ext: os.path.getsize(ext.sources[0]), reverse=True)
177

178
    from Cython.Distutils.build_ext import build_ext as cy_build_ext
179
    build_ext = None
180
    try:
181
        # Use the setuptools build_ext in preference, because it
182
        # gets limited api filenames right, and should inherit itself from
183
        # Cython's own build_ext. But failing that, use the Cython build_ext
184
        # directly.
185
        from setuptools.command.build_ext import build_ext
186
        if cy_build_ext not in build_ext.__mro__:
187
            build_ext = cy_build_ext
188
    except ImportError:
189
        build_ext = cy_build_ext
190

191
    from Cython.Compiler.Options import get_directive_defaults
192
    get_directive_defaults().update(
193
        language_level=3,
194
        auto_pickle=False,
195
        binding=False,
196
        always_allow_keywords=False,
197
        autotestdict=False,
198
    )
199
    if profile:
200
        get_directive_defaults()['profile'] = True
201
        sys.stderr.write("Enabled profiling for the Cython binary modules\n")
202
    if coverage:
203
        get_directive_defaults()['linetrace'] = True
204
        sys.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 requested
207
    add_command_class("build_ext", build_ext)
208
    setup_args['ext_modules'] = extensions
209

210

211
def check_option(name):
212
    cli_arg = "--" + name
213
    if cli_arg in sys.argv:
214
        sys.argv.remove(cli_arg)
215
        return True
216

217
    env_var = name.replace("-", "_").upper()
218
    if os.environ.get(env_var) == "true":
219
        return True
220

221
    return False
222

223

224
cython_profile = check_option('cython-profile')
225
cython_coverage = check_option('cython-coverage')
226
cython_with_refnanny = check_option('cython-with-refnanny')
227

228
compile_cython_itself = not check_option('no-cython-compile')
229
if compile_cython_itself:
230
    cython_compile_more = check_option('cython-compile-all')
231
    cython_compile_minimal = check_option('cython-compile-minimal')
232
    cython_limited_api = check_option('cython-limited-api')
233
    # TODO - enable this when refnanny can be compiled
234
    if cython_limited_api and False:
235
        setup_options = setup_args.setdefault('options', {})
236
        bdist_wheel_options = setup_options.setdefault('bdist_wheel', {})
237
        bdist_wheel_options['py_limited_api'] = 'cp37'
238

239

240
setup_args.update(setuptools_extra_args)
241

242

243
def dev_status(version: str):
244
    if 'b' in version or 'c' in version:
245
        # 1b1, 1beta1, 2rc1, ...
246
        return 'Development Status :: 4 - Beta'
247
    elif 'a' in version:
248
        # 1a1, 1alpha1, ...
249
        return 'Development Status :: 3 - Alpha'
250
    else:
251
        return 'Development Status :: 5 - Production/Stable'
252

253

254
packages = [
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

272
def run_build():
273
    if compile_cython_itself and (is_cpython or cython_compile_more or cython_compile_minimal):
274
        compile_cython_modules(cython_profile, cython_coverage, cython_compile_minimal, cython_compile_more, cython_with_refnanny,
275
                               cython_limited_api)
276

277
    from Cython import __version__ as version
278
    setup(
279
        name='Cython',
280
        version=version,
281
        url='https://cython.org/',
282
        author='Robert Bradshaw, Stefan Behnel, David Woods, Greg Ewing, et al.',
283
        author_email='cython-devel@python.org',
284
        description="The Cython compiler for writing C extensions in the Python language.",
285
        long_description=textwrap.dedent("""\
286
        The Cython language makes writing C extensions for the Python language as
287
        easy as Python itself.  Cython is a source code translator based on Pyrex_,
288
        but supports more cutting edge functionality and optimizations.
289

290
        The Cython language is a superset of the Python language (almost all Python
291
        code is also valid Cython code), but Cython additionally supports optional
292
        static typing to natively call C functions, operate with C++ classes and
293
        declare fast C types on variables and class attributes.  This allows the
294
        compiler to generate very efficient C code from Cython code.
295

296
        This makes Cython the ideal language for writing glue code for external
297
        C/C++ libraries, and for fast C modules that speed up the execution of
298
        Python code.
299

300
        The newest Cython release can always be downloaded from https://cython.org/.
301
        Unpack the tarball or zip file, enter the directory, and then run::
302

303
            pip install .
304

305
        Note that for one-time builds, e.g. for CI/testing, on platforms that are not
306
        covered by one of the wheel packages provided on PyPI *and* the pure Python wheel
307
        that we provide is not used, it is substantially faster than a full source build
308
        to install an uncompiled (slower) version of Cython with::
309

310
            NO_CYTHON_COMPILE=true pip install .
311

312
        .. _Pyrex: https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
313
        """),
314
        license='Apache-2.0',
315
        classifiers=[
316
            dev_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
        ],
340
        project_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

348
        scripts=scripts,
349
        packages=packages,
350
        py_modules=["cython"],
351
        **setup_args
352
    )
353

354

355
if __name__ == '__main__':
356
    run_build()
357

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.