Home | History | Annotate | Download | only in src
      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 sys
      8 
      9 try:
     10     import platform
     11     is_cpython = not hasattr(platform, 'python_implementation') or platform.python_implementation() == 'CPython'
     12 except (ImportError, NameError):
     13     is_cpython = True # CPython < 2.6
     14 
     15 if sys.platform == "darwin":
     16     # Don't create resource files on OS X tar.
     17     os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
     18     os.environ['COPYFILE_DISABLE'] = 'true'
     19 
     20 setup_args = {}
     21 
     22 def add_command_class(name, cls):
     23     cmdclasses = setup_args.get('cmdclass', {})
     24     cmdclasses[name] = cls
     25     setup_args['cmdclass'] = cmdclasses
     26 
     27 from distutils.command.sdist import sdist as sdist_orig
     28 class sdist(sdist_orig):
     29     def run(self):
     30         self.force_manifest = 1
     31         if (sys.platform != "win32" and 
     32             os.path.isdir('.git')):
     33             assert os.system("git rev-parse --verify HEAD > .gitrev") == 0
     34         sdist_orig.run(self)
     35 add_command_class('sdist', sdist)
     36 
     37 if sys.version_info[0] >= 3:
     38     import lib2to3.refactor
     39     from distutils.command.build_py \
     40          import build_py_2to3 as build_py
     41     # need to convert sources to Py3 on installation
     42     fixers = [ fix for fix in lib2to3.refactor.get_fixers_from_package("lib2to3.fixes")
     43                if fix.split('fix_')[-1] not in ('next',)
     44                ]
     45     build_py.fixer_names = fixers
     46     add_command_class("build_py", build_py)
     47 
     48 pxd_include_dirs = [
     49     directory for directory, dirs, files in os.walk('Cython/Includes')
     50     if '__init__.pyx' in files or '__init__.pxd' in files
     51     or directory == 'Cython/Includes' or directory == 'Cython/Includes/Deprecated']
     52 
     53 pxd_include_patterns = [
     54     p+'/*.pxd' for p in pxd_include_dirs ] + [
     55     p+'/*.pyx' for p in pxd_include_dirs ]
     56 
     57 setup_args['package_data'] = {
     58     'Cython.Plex'     : ['*.pxd'],
     59     'Cython.Compiler' : ['*.pxd'],
     60     'Cython.Runtime'  : ['*.pyx', '*.pxd'],
     61     'Cython.Utility'  : ['*.pyx', '*.pxd', '*.c', '*.h', '*.cpp'],
     62     'Cython'          : [ p[7:] for p in pxd_include_patterns ],
     63     }
     64 
     65 # This dict is used for passing extra arguments that are setuptools
     66 # specific to setup
     67 setuptools_extra_args = {}
     68 
     69 # tells whether to include cygdb (the script and the Cython.Debugger package
     70 include_debugger = sys.version_info[:2] > (2, 5)
     71 
     72 if 'setuptools' in sys.modules:
     73     setuptools_extra_args['zip_safe'] = False
     74     setuptools_extra_args['entry_points'] = {
     75         'console_scripts': [
     76             'cython = Cython.Compiler.Main:setuptools_main',
     77         ]
     78     }
     79     scripts = []
     80 else:
     81     if os.name == "posix":
     82         scripts = ["bin/cython"]
     83     else:
     84         scripts = ["cython.py"]
     85 
     86 if include_debugger:
     87     if 'setuptools' in sys.modules:
     88         setuptools_extra_args['entry_points']['console_scripts'].append(
     89             'cygdb = Cython.Debugger.Cygdb:main')
     90     else:
     91         if os.name == "posix":
     92             scripts.append('bin/cygdb')
     93         else:
     94             scripts.append('cygdb.py')
     95 
     96 
     97 def compile_cython_modules(profile=False, compile_more=False, cython_with_refnanny=False):
     98     source_root = os.path.abspath(os.path.dirname(__file__))
     99     compiled_modules = ["Cython.Plex.Scanners",
    100                         "Cython.Plex.Actions",
    101                         "Cython.Compiler.Lexicon",
    102                         "Cython.Compiler.Scanning",
    103                         "Cython.Compiler.Parsing",
    104                         "Cython.Compiler.Visitor",
    105                         "Cython.Compiler.FlowControl",
    106                         "Cython.Compiler.Code",
    107                         "Cython.Runtime.refnanny",
    108                         # "Cython.Compiler.FusedNode",
    109                         "Cython.Tempita._tempita",
    110                         ]
    111     if compile_more:
    112         compiled_modules.extend([
    113             "Cython.Build.Dependencies",
    114             "Cython.Compiler.ParseTreeTransforms",
    115             "Cython.Compiler.Nodes",
    116             "Cython.Compiler.ExprNodes",
    117             "Cython.Compiler.ModuleNode",
    118             "Cython.Compiler.Optimize",
    119             ])
    120 
    121     defines = []
    122     if cython_with_refnanny:
    123         defines.append(('CYTHON_REFNANNY', '1'))
    124 
    125     extensions = []
    126     if sys.version_info[0] >= 3:
    127         from Cython.Distutils import build_ext as build_ext_orig
    128         for module in compiled_modules:
    129             source_file = os.path.join(source_root, *module.split('.'))
    130             if os.path.exists(source_file + ".py"):
    131                 pyx_source_file = source_file + ".py"
    132             else:
    133                 pyx_source_file = source_file + ".pyx"
    134             dep_files = []
    135             if os.path.exists(source_file + '.pxd'):
    136                 dep_files.append(source_file + '.pxd')
    137             if '.refnanny' in module:
    138                 defines_for_module = []
    139             else:
    140                 defines_for_module = defines
    141             extensions.append(
    142                 Extension(module, sources = [pyx_source_file],
    143                           define_macros = defines_for_module,
    144                           depends = dep_files)
    145                 )
    146 
    147         class build_ext(build_ext_orig):
    148             # we must keep the original modules alive to make sure
    149             # their code keeps working when we remove them from
    150             # sys.modules
    151             dead_modules = []
    152 
    153             def build_extensions(self):
    154                 # add path where 2to3 installed the transformed sources
    155                 # and make sure Python (re-)imports them from there
    156                 already_imported = [ module for module in sys.modules
    157                                      if module == 'Cython' or module.startswith('Cython.') ]
    158                 keep_alive = self.dead_modules.append
    159                 for module in already_imported:
    160                     keep_alive(sys.modules[module])
    161                     del sys.modules[module]
    162                 sys.path.insert(0, os.path.join(source_root, self.build_lib))
    163 
    164                 if profile:
    165                     from Cython.Compiler.Options import directive_defaults
    166                     directive_defaults['profile'] = True
    167                     print("Enabled profiling for the Cython binary modules")
    168                 build_ext_orig.build_extensions(self)
    169 
    170         setup_args['ext_modules'] = extensions
    171         add_command_class("build_ext", build_ext)
    172 
    173     else: # Python 2.x
    174         from distutils.command.build_ext import build_ext as build_ext_orig
    175         try:
    176             class build_ext(build_ext_orig):
    177                 def build_extension(self, ext, *args, **kargs):
    178                     try:
    179                         build_ext_orig.build_extension(self, ext, *args, **kargs)
    180                     except StandardError:
    181                         print("Compilation of '%s' failed" % ext.sources[0])
    182             from Cython.Compiler.Main import compile
    183             from Cython import Utils
    184             if profile:
    185                 from Cython.Compiler.Options import directive_defaults
    186                 directive_defaults['profile'] = True
    187                 print("Enabled profiling for the Cython binary modules")
    188             source_root = os.path.dirname(__file__)
    189             for module in compiled_modules:
    190                 source_file = os.path.join(source_root, *module.split('.'))
    191                 if os.path.exists(source_file + ".py"):
    192                     pyx_source_file = source_file + ".py"
    193                 else:
    194                     pyx_source_file = source_file + ".pyx"
    195                 c_source_file = source_file + ".c"
    196                 source_is_newer = False
    197                 if not os.path.exists(c_source_file):
    198                     source_is_newer = True
    199                 else:
    200                     c_last_modified = Utils.modification_time(c_source_file)
    201                     if Utils.file_newer_than(pyx_source_file, c_last_modified):
    202                         source_is_newer = True
    203                     else:
    204                         pxd_source_file = source_file + ".pxd"
    205                         if os.path.exists(pxd_source_file) and Utils.file_newer_than(pxd_source_file, c_last_modified):
    206                             source_is_newer = True
    207                 if source_is_newer:
    208                     print("Compiling module %s ..." % module)
    209                     result = compile(pyx_source_file)
    210                     c_source_file = result.c_file
    211                 if c_source_file:
    212                     # Py2 distutils can't handle unicode file paths
    213                     if isinstance(c_source_file, unicode):
    214                         filename_encoding = sys.getfilesystemencoding()
    215                         if filename_encoding is None:
    216                             filename_encoding = sys.getdefaultencoding()
    217                         c_source_file = c_source_file.encode(filename_encoding)
    218                     if '.refnanny' in module:
    219                         defines_for_module = []
    220                     else:
    221                         defines_for_module = defines
    222                     extensions.append(
    223                         Extension(module, sources = [c_source_file],
    224                                   define_macros = defines_for_module)
    225                         )
    226                 else:
    227                     print("Compilation failed")
    228             if extensions:
    229                 setup_args['ext_modules'] = extensions
    230                 add_command_class("build_ext", build_ext)
    231         except Exception:
    232             print('''
    233 ERROR: %s
    234 
    235 Extension module compilation failed, looks like Cython cannot run
    236 properly on this system.  To work around this, pass the option
    237 "--no-cython-compile".  This will install a pure Python version of
    238 Cython without compiling its own sources.
    239 ''' % sys.exc_info()[1])
    240             raise
    241 
    242 cython_profile = '--cython-profile' in sys.argv
    243 if cython_profile:
    244     sys.argv.remove('--cython-profile')
    245 
    246 try:
    247     sys.argv.remove("--cython-compile-all")
    248     cython_compile_more = True
    249 except ValueError:
    250     cython_compile_more = False
    251 
    252 try:
    253     sys.argv.remove("--cython-with-refnanny")
    254     cython_with_refnanny = True
    255 except ValueError:
    256     cython_with_refnanny = False
    257 
    258 try:
    259     sys.argv.remove("--no-cython-compile")
    260     compile_cython_itself = False
    261 except ValueError:
    262     compile_cython_itself = True
    263 
    264 if compile_cython_itself and (is_cpython or cython_compile_more):
    265     compile_cython_modules(cython_profile, cython_compile_more, cython_with_refnanny)
    266 
    267 setup_args.update(setuptools_extra_args)
    268 
    269 from Cython import __version__ as version
    270 
    271 packages = [
    272     'Cython',
    273     'Cython.Build',
    274     'Cython.Compiler',
    275     'Cython.Runtime',
    276     'Cython.Distutils',
    277     'Cython.Plex',
    278     'Cython.Tests',
    279     'Cython.Build.Tests',
    280     'Cython.Compiler.Tests',
    281     'Cython.Utility',
    282     'Cython.Tempita',
    283     'pyximport',
    284 ]
    285 
    286 if include_debugger:
    287     packages.append('Cython.Debugger')
    288     packages.append('Cython.Debugger.Tests')
    289     # it's enough to do this for Py2.5+:
    290     setup_args['package_data']['Cython.Debugger.Tests'] = ['codefile', 'cfuncs.c']
    291 
    292 setup(
    293   name = 'Cython',
    294   version = version,
    295   url = 'http://www.cython.org',
    296   author = 'Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.',
    297   author_email = 'cython-devel (at] python.org',
    298   description = "The Cython compiler for writing C extensions for the Python language.",
    299   long_description = """\
    300   The Cython language makes writing C extensions for the Python language as
    301   easy as Python itself.  Cython is a source code translator based on the
    302   well-known Pyrex_, but supports more cutting edge functionality and
    303   optimizations.
    304 
    305   The Cython language is very close to the Python language (and most Python
    306   code is also valid Cython code), but Cython additionally supports calling C
    307   functions and declaring C types on variables and class attributes. This
    308   allows the compiler to generate very efficient C code from Cython code.
    309 
    310   This makes Cython the ideal language for writing glue code for external C
    311   libraries, and for fast C modules that speed up the execution of Python
    312   code.
    313 
    314   .. _Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
    315   """,
    316   classifiers = [
    317     "Development Status :: 5 - Production/Stable",
    318     "Intended Audience :: Developers",
    319     "License :: OSI Approved :: Apache Software License",
    320     "Operating System :: OS Independent",
    321     "Programming Language :: Python",
    322     "Programming Language :: Python :: 2",
    323     "Programming Language :: Python :: 3",
    324     "Programming Language :: C",
    325     "Programming Language :: Cython",
    326     "Topic :: Software Development :: Code Generators",
    327     "Topic :: Software Development :: Compilers",
    328     "Topic :: Software Development :: Libraries :: Python Modules"
    329   ],
    330 
    331   scripts = scripts,
    332   packages=packages,
    333 
    334   py_modules = ["cython"],
    335 
    336   **setup_args
    337   )
    338